[0-9]+(?:\.[0-9]+)*) # release
+ (? # prerelease
+ [-_\.]?
+ (?(a|b|c|rc|alpha|beta|pre|preview))
+ [-_\.]?
+ (?[0-9]+)?
+ )?
+ (? # post release
+ (?:-(?[0-9]+))
+ |
+ (?:
+ [-_\.]?
+ (?post|rev|r)
+ [-_\.]?
+ (?[0-9]+)?
+ )
+ )?
+ (? # dev release
+ [-_\.]?
+ (?dev)
+ [-_\.]?
+ (?[0-9]+)?
+ )?
+ )
+ (?:\+(?[a-z0-9]+(?:[-_\.][a-z0-9]+)*))? # local version
+ /ix
+
+ ANCHORED_VERSION_PATTERN = /\A\s*#{VERSION_PATTERN}\s*\z/
+
+ sig { override.params(version: VersionParameter).returns(T::Boolean) }
+ def self.correct?(version)
+ return false if version.nil?
+
+ version.to_s.match?(ANCHORED_VERSION_PATTERN)
+ end
+
+ sig { override.params(version: VersionParameter).void }
+ def initialize(version)
+ raise Dependabot::BadRequirementError, "Malformed version string - string is nil" if version.nil?
+
+ @version_string = version.to_s
+
+ raise Dependabot::BadRequirementError, "Malformed version string - string is empty" if @version_string.empty?
+
+ matches = ANCHORED_VERSION_PATTERN.match(@version_string.downcase)
+
+ unless matches
+ raise Dependabot::BadRequirementError,
+ "Malformed version string - #{@version_string} does not match regex"
+ end
+
+ @epoch = matches["epoch"].to_i
+ @release_segment = matches["release"]&.split(".")&.map(&:to_i) || []
+ @pre = parse_letter_version(matches["pre_l"], matches["pre_n"])
+ @post = parse_letter_version(matches["post_l"], matches["post_n1"] || matches["post_n2"])
+ @dev = parse_letter_version(matches["dev_l"], matches["dev_n"])
+ @local = parse_local_version(matches["local"])
+ super(matches["release"] || "")
+ end
+
+ sig { override.params(version: VersionParameter).returns(Dependabot::Uv::Version) }
+ def self.new(version)
+ T.cast(super, Dependabot::Uv::Version)
+ end
+
+ sig { returns(String) }
+ def to_s
+ @version_string
+ end
+
+ sig { returns(String) }
+ def inspect # :nodoc:
+ "#<#{self.class} #{@version_string}>"
+ end
+
+ sig { returns(T::Boolean) }
+ def prerelease?
+ !!(pre || dev)
+ end
+
+ sig { returns(Dependabot::Uv::Version) }
+ def release
+ Dependabot::Uv::Version.new(release_segment.join("."))
+ end
+
+ sig { params(other: VersionParameter).returns(Integer) }
+ def <=>(other)
+ other = Dependabot::Uv::Version.new(other.to_s) unless other.is_a?(Dependabot::Uv::Version)
+ other = T.cast(other, Dependabot::Uv::Version)
+
+ epoch_comparison = epoch <=> other.epoch
+ return epoch_comparison unless epoch_comparison.zero?
+
+ release_comparison = release_version_comparison(other)
+ return release_comparison unless release_comparison.zero?
+
+ pre_comparison = compare_keys(pre_cmp_key, other.pre_cmp_key)
+ return pre_comparison unless pre_comparison.zero?
+
+ post_comparison = compare_keys(post_cmp_key, other.post_cmp_key)
+ return post_comparison unless post_comparison.zero?
+
+ dev_comparison = compare_keys(dev_cmp_key, other.dev_cmp_key)
+ return dev_comparison unless dev_comparison.zero?
+
+ compare_keys(local_cmp_key, other.local_cmp_key)
+ end
+
+ sig do
+ params(
+ key: T.any(Integer, T::Array[T.any(String, Integer)]),
+ other_key: T.any(Integer, T::Array[T.any(String, Integer)])
+ ).returns(Integer)
+ end
+ def compare_keys(key, other_key)
+ if key.is_a?(Integer) && other_key.is_a?(Integer)
+ key <=> other_key
+ elsif key.is_a?(Array) && other_key.is_a?(Array)
+ key <=> other_key
+ elsif key.is_a?(Integer)
+ key == NEGATIVE_INFINITY ? -1 : 1
+ elsif other_key.is_a?(Integer)
+ other_key == NEGATIVE_INFINITY ? 1 : -1
+ end
+ end
+
+ sig { returns(T.any(Integer, T::Array[T.any(String, Integer)])) }
+ def pre_cmp_key
+ if pre.nil? && post.nil? && dev # sort 1.0.dev0 before 1.0a0
+ NEGATIVE_INFINITY
+ elsif pre.nil?
+ INFINITY # versions without a pre-release should sort after those with one.
+ else
+ T.must(pre)
+ end
+ end
+
+ sig { returns(T.any(Integer, T::Array[T.any(String, Integer)])) }
+ def local_cmp_key
+ if local.nil?
+ # Versions without a local segment should sort before those with one.
+ NEGATIVE_INFINITY
+ else
+ # According to PEP440.
+ # - Alphanumeric segments sort before numeric segments
+ # - Alphanumeric segments sort lexicographically
+ # - Numeric segments sort numerically
+ # - Shorter versions sort before longer versions when the prefixes match exactly
+ local&.map do |token|
+ if token.is_a?(Integer)
+ [token, ""]
+ else
+ [NEGATIVE_INFINITY, token]
+ end
+ end
+ end
+ end
+
+ sig { returns(T.any(Integer, T::Array[T.any(String, Integer)])) }
+ def post_cmp_key
+ # Versions without a post segment should sort before those with one.
+ return NEGATIVE_INFINITY if post.nil?
+
+ T.must(post)
+ end
+
+ sig { returns(T.any(Integer, T::Array[T.any(String, Integer)])) }
+ def dev_cmp_key
+ # Versions without a dev segment should sort after those with one.
+ return INFINITY if dev.nil?
+
+ T.must(dev)
+ end
+
+ sig { returns(String) }
+ def lowest_prerelease_suffix
+ "dev0"
+ end
+
+ sig { override.returns(T::Array[String]) }
+ def ignored_patch_versions
+ parts = release_segment # e.g [1,2,3] if version is 1.2.3-alpha3
+ version_parts = parts.fill(0, parts.length...2)
+ upper_parts = version_parts.first(1) + [version_parts[1].to_i + 1] + [lowest_prerelease_suffix]
+ lower_bound = "> #{self}"
+ upper_bound = "< #{upper_parts.join('.')}"
+
+ ["#{lower_bound}, #{upper_bound}"]
+ end
+
+ sig { override.returns(T::Array[String]) }
+ def ignored_minor_versions
+ parts = release_segment # e.g [1,2,3] if version is 1.2.3-alpha3
+ version_parts = parts.fill(0, parts.length...2)
+ lower_parts = version_parts.first(1) + [version_parts[1].to_i + 1] + [lowest_prerelease_suffix]
+ upper_parts = version_parts.first(0) + [version_parts[0].to_i + 1] + [lowest_prerelease_suffix]
+ lower_bound = ">= #{lower_parts.join('.')}"
+ upper_bound = "< #{upper_parts.join('.')}"
+
+ ["#{lower_bound}, #{upper_bound}"]
+ end
+
+ sig { override.returns(T::Array[String]) }
+ def ignored_major_versions
+ version_parts = release_segment # e.g [1,2,3] if version is 1.2.3-alpha3
+ lower_parts = [version_parts[0].to_i + 1] + [lowest_prerelease_suffix] # earliest next major version prerelease
+ lower_bound = ">= #{lower_parts.join('.')}"
+
+ [lower_bound]
+ end
+
+ private
+
+ sig { params(other: Dependabot::Uv::Version).returns(Integer) }
+ def release_version_comparison(other)
+ tokens, other_tokens = pad_for_comparison(release_segment, other.release_segment)
+ tokens <=> other_tokens
+ end
+
+ sig do
+ params(
+ tokens: T::Array[Integer],
+ other_tokens: T::Array[Integer]
+ ).returns(T::Array[T::Array[Integer]])
+ end
+ def pad_for_comparison(tokens, other_tokens)
+ tokens = tokens.dup
+ other_tokens = other_tokens.dup
+
+ longer = [tokens, other_tokens].max_by(&:count)
+ shorter = [tokens, other_tokens].min_by(&:count)
+
+ difference = T.must(longer).length - T.must(shorter).length
+
+ difference.times { T.must(shorter) << 0 }
+
+ [tokens, other_tokens]
+ end
+
+ sig { params(local: T.nilable(String)).returns(T.nilable(T::Array[T.any(String, Integer)])) }
+ def parse_local_version(local)
+ return if local.nil?
+
+ # Takes a string like abc.1.twelve and turns it into ["abc", 1, "twelve"]
+ local.split(/[\._-]/).map { |s| /^\d+$/.match?(s) ? s.to_i : s }
+ end
+
+ sig do
+ params(
+ letter: T.nilable(String), number: T.nilable(String)
+ ).returns(T.nilable(T::Array[T.any(String, Integer)]))
+ end
+ def parse_letter_version(letter = nil, number = nil)
+ return if letter.nil? && number.nil?
+
+ if letter
+ # Implicit 0 for cases where prerelease has no numeral
+ number ||= 0
+
+ # Normalize alternate spellings
+ if letter == "alpha"
+ letter = "a"
+ elsif letter == "beta"
+ letter = "b"
+ elsif %w(c pre preview).include? letter
+ letter = "rc"
+ elsif %w(rev r).include? letter
+ letter = "post"
+ end
+
+ return letter, number.to_i
+ end
+
+ # Number but no letter i.e. implicit post release syntax (e.g. 1.0-1)
+ letter = "post"
+
+ [letter, number.to_i]
+ end
+ end
+ end
+end
+
+Dependabot::Utils
+ .register_version_class("uv", Dependabot::Uv::Version)
diff --git a/uv/script/ci-test b/uv/script/ci-test
new file mode 100755
index 00000000000..1fd0a4967c1
--- /dev/null
+++ b/uv/script/ci-test
@@ -0,0 +1,8 @@
+#!/usr/bin/env bash
+
+set -e
+
+pyenv exec flake8 helpers/. --count --exclude=./.*,./uv/spec/fixtures --show-source --statistics
+
+bundle install
+bundle exec turbo_tests --verbose
diff --git a/uv/spec/dependabot/uv/authed_url_builder_spec.rb b/uv/spec/dependabot/uv/authed_url_builder_spec.rb
new file mode 100644
index 00000000000..0ca4e12f929
--- /dev/null
+++ b/uv/spec/dependabot/uv/authed_url_builder_spec.rb
@@ -0,0 +1,119 @@
+# typed: false
+# frozen_string_literal: true
+
+require "spec_helper"
+require "dependabot/credential"
+require "dependabot/uv/authed_url_builder"
+
+RSpec.describe Dependabot::Uv::AuthedUrlBuilder do
+ describe ".authed_url" do
+ subject(:authed_url) { described_class.authed_url(credential: credential) }
+
+ context "without index-url" do
+ let(:credential) do
+ Dependabot::Credential.new({
+ "type" => "python_index",
+ "replaces-base" => true
+ })
+ end
+
+ it "returns empty string" do
+ expect(authed_url)
+ .to eq("")
+ end
+ end
+
+ context "without a token" do
+ let(:credential) do
+ Dependabot::Credential.new({
+ "type" => "python_index",
+ "index-url" => "https://pypi.weasyldev.com/weasyl/source/+simple",
+ "replaces-base" => true
+ })
+ end
+
+ it "leaves the URL alone" do
+ expect(authed_url)
+ .to eq("https://pypi.weasyldev.com/weasyl/source/+simple")
+ end
+ end
+
+ context "with a token" do
+ let(:credential) do
+ Dependabot::Credential.new({
+ "type" => "python_index",
+ "index-url" => "https://pypi.weasyldev.com/weasyl/source/+simple",
+ "token" => token,
+ "replaces-base" => true
+ })
+ end
+
+ context "when not including a :" do
+ let(:token) { "token" }
+
+ it "builds the URL correctly" do
+ expect(authed_url)
+ .to eq("https://token@pypi.weasyldev.com/weasyl/source/+simple")
+ end
+
+ context "when already base64 encoded" do
+ let(:token) { "bXk6cGFzcw==" }
+
+ it "builds the URL correctly" do
+ expect(authed_url)
+ .to eq("https://my:pass@pypi.weasyldev.com/weasyl/source/+simple")
+ end
+ end
+ end
+
+ context "when including a :" do
+ let(:token) { "token:pass" }
+
+ it "builds the URL correctly" do
+ expect(authed_url)
+ .to eq("https://token:pass@pypi.weasyldev.com/weasyl/source/+simple")
+ end
+ end
+
+ context "when including an @" do
+ let(:token) { "token:pass@23" }
+
+ it "builds the URL correctly" do
+ expect(authed_url). to eq(
+ "https://token:pass%4023@pypi.weasyldev.com/weasyl/source/+simple"
+ )
+ end
+ end
+
+ context "when including an #" do
+ let(:token) { "token:pass#23" }
+
+ it "builds the URL correctly" do
+ expect(authed_url). to eq(
+ "https://token:pass%2323@pypi.weasyldev.com/weasyl/source/+simple"
+ )
+ end
+ end
+
+ context "when there are multiple colons" do
+ let(:token) { "token:pass:23" }
+
+ it "builds the URL correctly" do
+ expect(authed_url). to eq(
+ "https://token:pass%3A23@pypi.weasyldev.com/weasyl/source/+simple"
+ )
+ end
+ end
+
+ context "when including an @ and is base64 encoded" do
+ let(:token) { "dG9rZW46cGFzc0AyMw==" }
+
+ it "builds the URL correctly" do
+ expect(authed_url). to eq(
+ "https://token:pass%4023@pypi.weasyldev.com/weasyl/source/+simple"
+ )
+ end
+ end
+ end
+ end
+end
diff --git a/uv/spec/dependabot/uv/file_fetcher_spec.rb b/uv/spec/dependabot/uv/file_fetcher_spec.rb
new file mode 100644
index 00000000000..ed56c4da393
--- /dev/null
+++ b/uv/spec/dependabot/uv/file_fetcher_spec.rb
@@ -0,0 +1,751 @@
+# typed: false
+# frozen_string_literal: true
+
+require "spec_helper"
+require "dependabot/uv/file_fetcher"
+require_common_spec "file_fetchers/shared_examples_for_file_fetchers"
+
+RSpec.describe Dependabot::Uv::FileFetcher do
+ it_behaves_like "a dependency file fetcher"
+
+ describe ".required_files_in?" do
+ subject { described_class.required_files_in?(filenames) }
+
+ context "with only a requirements.in" do
+ let(:filenames) { %w(requirements.in) }
+
+ it { is_expected.to be(true) }
+ end
+
+ context "with only a requirements.txt" do
+ let(:filenames) { %w(requirements.txt) }
+
+ it { is_expected.to be(true) }
+ end
+
+ context "with only a requirements folder" do
+ let(:filenames) { %w(requirements) }
+
+ it { is_expected.to be(true) }
+ end
+
+ context "with only a requirements-dev" do
+ let(:filenames) { %w(requirements-dev.txt) }
+
+ it { is_expected.to be(true) }
+ end
+
+ context "with a pyproject.toml" do
+ let(:filenames) { %w(pyproject.toml) }
+
+ it { is_expected.to be(true) }
+ end
+
+ context "with no requirements" do
+ let(:filenames) { %w(requirements-dev.md) }
+
+ it { is_expected.to be(false) }
+ end
+ end
+
+ describe "#files" do
+ let(:source) do
+ Dependabot::Source.new(
+ provider: "github",
+ repo: "gocardless/bump",
+ directory: directory
+ )
+ end
+ let(:directory) { "/" }
+ let(:file_fetcher_instance) do
+ described_class.new(source: source, credentials: credentials)
+ end
+ let(:url) { "https://api.github.com/repos/gocardless/bump/contents/" }
+ let(:url_with_directory) { File.join(url, directory) }
+ let(:credentials) do
+ [Dependabot::Credential.new({
+ "type" => "git_source",
+ "host" => "github.com",
+ "username" => "x-access-token",
+ "password" => "token"
+ })]
+ end
+
+ let(:json_header) { { "content-type" => "application/json" } }
+ let(:repo_contents) do
+ fixture("github", "contents_python_only_requirements.json")
+ end
+
+ before do
+ allow(file_fetcher_instance).to receive(:commit).and_return("sha")
+
+ stub_request(:get, url + "?ref=sha")
+ .with(headers: { "Authorization" => "token token" })
+ .to_return(status: 200, body: repo_contents, headers: json_header)
+
+ %w(app build_scripts data migrations tests).each do |dir|
+ stub_request(:get, File.join(url_with_directory, "#{dir}?ref=sha"))
+ .with(headers: { "Authorization" => "token token" })
+ .to_return(status: 200, body: "[]", headers: json_header)
+ end
+
+ stub_request(:get, File.join(url_with_directory, "todo.txt?ref=sha"))
+ .with(headers: { "Authorization" => "token token" })
+ .to_return(
+ status: 200,
+ body: fixture("github", "contents_todo_txt.json"),
+ headers: json_header
+ )
+ end
+
+ context "with only a requirements.in" do
+ let(:repo_contents) do
+ fixture("github", "contents_python_only_requirements_in.json")
+ end
+
+ before do
+ stub_request(:get, url + "requirements.in?ref=sha")
+ .with(headers: { "Authorization" => "token token" })
+ .to_return(
+ status: 200,
+ body: fixture("github", "requirements_in_content.json"),
+ headers: { "content-type" => "application/json" }
+ )
+ end
+
+ it "fetches the requirements.in file" do
+ expect(file_fetcher_instance.files.count).to eq(1)
+ expect(file_fetcher_instance.files.map(&:name))
+ .to eq(["requirements.in"])
+ end
+ end
+
+ context "with only a requirements.txt" do
+ let(:repo_contents) do
+ fixture("github", "contents_python_only_requirements.json")
+ end
+ let(:requirements_fixture_name) { "requirements_content.json" }
+
+ before do
+ stub_request(:get, url + "requirements.txt?ref=sha")
+ .with(headers: { "Authorization" => "token token" })
+ .to_return(
+ status: 200,
+ body: fixture("github", requirements_fixture_name),
+ headers: { "content-type" => "application/json" }
+ )
+ end
+
+ it "fetches the requirements.txt file" do
+ expect(file_fetcher_instance.files.count).to eq(1)
+ expect(file_fetcher_instance.files.map(&:name))
+ .to eq(["requirements.txt"])
+ end
+
+ context "when including comments" do
+ let(:requirements_fixture_name) { "requirements_with_comments.json" }
+
+ it "fetches the requirements.txt file" do
+ expect(file_fetcher_instance.files.count).to eq(1)
+ expect(file_fetcher_instance.files.map(&:name))
+ .to eq(["requirements.txt"])
+ end
+ end
+
+ context "when including --no-binary" do
+ let(:requirements_fixture_name) { "requirements_with_no_binary.json" }
+
+ it "fetches the requirements.txt file" do
+ expect(file_fetcher_instance.files.count).to eq(1)
+ expect(file_fetcher_instance.files.map(&:name))
+ .to eq(["requirements.txt"])
+ end
+ end
+
+ context "when dealing with a todo.txt that is actually a requirements file" do
+ before do
+ stub_request(:get, url + "todo.txt?ref=sha")
+ .with(headers: { "Authorization" => "token token" })
+ .to_return(
+ status: 200,
+ body: fixture("github", todo_fixture_name),
+ headers: { "content-type" => "application/json" }
+ )
+ end
+
+ let(:todo_fixture_name) { "requirements_content.json" }
+
+ it "fetches the unexpectedly named file" do
+ expect(file_fetcher_instance.files.count).to eq(2)
+ expect(file_fetcher_instance.files.map(&:name))
+ .to match_array(%w(todo.txt requirements.txt))
+ end
+
+ context "when including comments" do
+ let(:todo_fixture_name) { "requirements_with_comments.json" }
+
+ it "fetches the unexpectedly named file" do
+ expect(file_fetcher_instance.files.count).to eq(2)
+ expect(file_fetcher_instance.files.map(&:name))
+ .to match_array(%w(todo.txt requirements.txt))
+ end
+ end
+ end
+
+ context "when dealing with a todo.txt can't be encoded to UTF-8" do
+ before do
+ stub_request(:get, url + "todo.txt?ref=sha")
+ .with(headers: { "Authorization" => "token token" })
+ .to_return(
+ status: 200,
+ body: fixture("github", "contents_image.json"),
+ headers: { "content-type" => "application/json" }
+ )
+ end
+
+ it "fetches the requirements.txt file" do
+ expect(file_fetcher_instance.files.count).to eq(1)
+ expect(file_fetcher_instance.files.map(&:name))
+ .to eq(["requirements.txt"])
+ end
+ end
+ end
+
+ context "with only a pyproject.toml" do
+ let(:repo_contents) do
+ fixture("github", "contents_python_only_pyproject.json")
+ end
+
+ before do
+ stub_request(:get, url + "pyproject.toml?ref=sha")
+ .with(headers: { "Authorization" => "token token" })
+ .to_return(
+ status: 200,
+ body: fixture("github", "contents_python_pyproject.json"),
+ headers: { "content-type" => "application/json" }
+ )
+ end
+
+ it "fetches the pyproject.toml" do
+ expect(file_fetcher_instance.files.count).to eq(1)
+ expect(file_fetcher_instance.files.map(&:name))
+ .to match_array(%w(pyproject.toml))
+ end
+ end
+
+ context "with requirements.txt, requirements.in, or pyproject.toml" do
+ let(:repo_contents) { "[]" }
+
+ it "raises a Dependabot::DependencyFileNotFound error" do
+ expect { file_fetcher_instance.files }
+ .to raise_error(Dependabot::DependencyFileNotFound)
+ end
+ end
+
+ context "with a cascading requirement" do
+ let(:repo_contents) do
+ fixture("github", "contents_python_only_requirements.json")
+ end
+
+ before do
+ stub_request(:get, url + "requirements.txt?ref=sha")
+ .with(headers: { "Authorization" => "token token" })
+ .to_return(
+ status: 200,
+ body: fixture("github", "requirements_with_cascade.json"),
+ headers: { "content-type" => "application/json" }
+ )
+ end
+
+ context "when fetchable" do
+ before do
+ stub_request(:get, url + "more_requirements.txt?ref=sha")
+ .with(headers: { "Authorization" => "token token" })
+ .to_return(
+ status: 200,
+ body: fixture("github", "requirements_content.json"),
+ headers: { "content-type" => "application/json" }
+ )
+ stub_request(:get, url + "no_dot/more_requirements.txt?ref=sha")
+ .with(headers: { "Authorization" => "token token" })
+ .to_return(
+ status: 200,
+ body: fixture("github", "requirements_content.json"),
+ headers: { "content-type" => "application/json" }
+ )
+ stub_request(:get, url + "comment_more_requirements.txt?ref=sha")
+ .with(headers: { "Authorization" => "token token" })
+ .to_return(
+ status: 200,
+ body: fixture("github", "requirements_content.json"),
+ headers: { "content-type" => "application/json" }
+ )
+ end
+
+ it "fetches the additional requirements" do
+ expect(file_fetcher_instance.files.count).to eq(4)
+ expect(file_fetcher_instance.files.map(&:name))
+ .to include("more_requirements.txt")
+ .and include("no_dot/more_requirements.txt")
+ .and include("comment_more_requirements.txt")
+ end
+
+ context "when dealing with circular" do
+ before do
+ stub_request(:get, url + "requirements.txt?ref=sha")
+ .with(headers: { "Authorization" => "token token" })
+ .to_return(
+ status: 200,
+ body: fixture("github", "requirements_with_circular.json"),
+ headers: { "content-type" => "application/json" }
+ )
+ end
+
+ it "only fetches the additional requirements once" do
+ expect(file_fetcher_instance.files.count).to eq(1)
+ end
+ end
+
+ context "when dealing with a .in file" do
+ before do
+ stub_request(:get, url + "requirements.txt?ref=sha")
+ .with(headers: { "Authorization" => "token token" })
+ .to_return(
+ status: 200,
+ body: fixture("github", "requirements_with_in_child.json"),
+ headers: { "content-type" => "application/json" }
+ )
+ stub_request(:get, url + "some/nested/req.in?ref=sha")
+ .with(headers: { "Authorization" => "token token" })
+ .to_return(
+ status: 200,
+ body: fixture("github", "requirements_content.json"),
+ headers: { "content-type" => "application/json" }
+ )
+ end
+
+ it "fetches the .in file" do
+ expect(file_fetcher_instance.files.count).to eq(2)
+ expect(file_fetcher_instance.files.map(&:name))
+ .to include("some/nested/req.in")
+ end
+ end
+
+ context "when cascading more than once" do
+ before do
+ stub_request(:get, url + "no_dot/more_requirements.txt?ref=sha")
+ .with(headers: { "Authorization" => "token token" })
+ .to_return(
+ status: 200,
+ body: fixture(
+ "github", "requirements_with_simple_cascade.json"
+ ),
+ headers: { "content-type" => "application/json" }
+ )
+ stub_request(
+ :get, url + "no_dot/cascaded_requirements.txt?ref=sha"
+ ).with(headers: { "Authorization" => "token token" })
+ .to_return(
+ status: 200,
+ body: fixture("github", "requirements_content.json"),
+ headers: { "content-type" => "application/json" }
+ )
+ end
+
+ it "fetches the additional requirements" do
+ expect(file_fetcher_instance.files.count).to eq(5)
+ expect(file_fetcher_instance.files.map(&:name))
+ .to include("no_dot/more_requirements.txt")
+ .and include("no_dot/cascaded_requirements.txt")
+ end
+ end
+ end
+
+ context "when an unfetchable path is present" do
+ before do
+ stub_request(:get, url + "more_requirements.txt?ref=sha")
+ .with(headers: { "Authorization" => "token token" })
+ .to_return(status: 404)
+ end
+
+ it "raises a DependencyFileNotFound error with details" do
+ expect { file_fetcher_instance.files }
+ .to raise_error(Dependabot::DependencyFileNotFound)
+ end
+ end
+ end
+
+ context "with a constraints file" do
+ let(:repo_contents) do
+ fixture("github", "contents_python_only_requirements.json")
+ end
+
+ before do
+ stub_request(:get, url + "requirements.txt?ref=sha")
+ .with(headers: { "Authorization" => "token token" })
+ .to_return(
+ status: 200,
+ body: fixture("github", "requirements_with_constraint.json"),
+ headers: { "content-type" => "application/json" }
+ )
+ end
+
+ context "when fetchable" do
+ before do
+ stub_request(:get, url + "constraints.txt?ref=sha")
+ .with(headers: { "Authorization" => "token token" })
+ .to_return(
+ status: 200,
+ body: fixture("github", "python_constraints_content.json"),
+ headers: { "content-type" => "application/json" }
+ )
+ end
+
+ it "fetches the constraints file" do
+ expect(file_fetcher_instance.files.count).to eq(2)
+ expect(file_fetcher_instance.files.map(&:name))
+ .to include("constraints.txt")
+ end
+ end
+
+ context "when an unfetchable path is present" do
+ before do
+ stub_request(:get, url + "constraints.txt?ref=sha")
+ .with(headers: { "Authorization" => "token token" })
+ .to_return(status: 404)
+ end
+
+ it "raises a DependencyFileNotFound error with details" do
+ expect { file_fetcher_instance.files }
+ .to raise_error(Dependabot::DependencyFileNotFound)
+ end
+ end
+ end
+
+ context "with a path-based dependency that it's not fetchable" do
+ let(:directory) { "/requirements" }
+
+ let(:repo_contents) do
+ fixture("github", "contents_directory_with_outside_reference_root.json")
+ end
+
+ before do
+ stub_request(:get, url_with_directory + "?ref=sha")
+ .with(headers: { "Authorization" => "token token" })
+ .to_return(
+ status: 200,
+ body: fixture("github", "contents_directory_with_outside_reference.json"),
+ headers: { "content-type" => "application/json" }
+ )
+ stub_request(:get, File.join(url_with_directory, "base.in?ref=sha"))
+ .with(headers: { "Authorization" => "token token" })
+ .to_return(
+ status: 200,
+ body: fixture("github", "contents_directory_with_outside_reference_in_file.json"),
+ headers: { "content-type" => "application/json" }
+ )
+ stub_request(:get, File.join(url_with_directory, "base.txt?ref=sha"))
+ .with(headers: { "Authorization" => "token token" })
+ .to_return(
+ status: 200,
+ body: fixture("github", "contents_directory_with_outside_reference_txt_file.json"),
+ headers: { "content-type" => "application/json" }
+ )
+ stub_request(:get, File.join(url_with_directory, "setup.py?ref=sha"))
+ .with(headers: { "Authorization" => "token token" })
+ .to_return(status: 404)
+ stub_request(:get, File.join(url_with_directory, "pyproject.toml?ref=sha"))
+ .with(headers: { "Authorization" => "token token" })
+ .to_return(status: 404)
+ end
+
+ it "raises DependencyFileNotFound error with details" do
+ expect { file_fetcher_instance.files }
+ .to raise_error(
+ Dependabot::PathDependenciesNotReachable,
+ "The following path based dependencies could not be retrieved: \"-e file:.\" at /requirements/base.in"
+ )
+ end
+ end
+
+ context "with a path-based dependency that is fetchable" do
+ let(:repo_contents) do
+ fixture("github", "contents_python_only_requirements.json")
+ end
+
+ before do
+ stub_request(:get, url + "requirements.txt?ref=sha")
+ .with(headers: { "Authorization" => "token token" })
+ .to_return(
+ status: 200,
+ body: fixture("github", "requirements_with_self_reference.json"),
+ headers: { "content-type" => "application/json" }
+ )
+ stub_request(:get, url + "setup.py?ref=sha")
+ .with(headers: { "Authorization" => "token token" })
+ .to_return(
+ status: 200,
+ body: fixture("github", "setup_content.json"),
+ headers: { "content-type" => "application/json" }
+ )
+ stub_request(:get, url + "setup.cfg?ref=sha")
+ .with(headers: { "Authorization" => "token token" })
+ .to_return(
+ status: 404,
+ body: fixture("github", "setup_content.json"),
+ headers: { "content-type" => "application/json" }
+ )
+ stub_request(:get, url + "pyproject.toml?ref=sha")
+ .with(headers: { "Authorization" => "token token" })
+ .to_return(
+ status: 200,
+ body: fixture("github", "contents_python_pyproject.json"),
+ headers: { "content-type" => "application/json" }
+ )
+ end
+
+ it "fetches the setup.py" do
+ expect(file_fetcher_instance.files.count).to eq(2)
+ expect(file_fetcher_instance.files.map(&:name)).to include("requirements.txt")
+ expect(file_fetcher_instance.files.map(&:name)).to include("pyproject.toml")
+ end
+
+ context "when using a variety of quote styles" do
+ before do
+ stub_request(:get, url + "requirements.txt?ref=sha")
+ .with(headers: { "Authorization" => "token token" })
+ .to_return(
+ status: 200,
+ body:
+ fixture("github", "requirements_with_path_dependencies.json"),
+ headers: { "content-type" => "application/json" }
+ )
+ stub_request(:get, url + "my/setup.py?ref=sha")
+ .with(headers: { "Authorization" => "token token" })
+ .to_return(
+ status: 200,
+ body: fixture("github", "setup_content.json"),
+ headers: { "content-type" => "application/json" }
+ )
+ stub_request(:get, url + "my/setup.cfg?ref=sha")
+ .with(headers: { "Authorization" => "token token" })
+ .to_return(status: 404)
+ stub_request(:get, url + "my?ref=sha")
+ .with(headers: { "Authorization" => "token token" })
+ .to_return(
+ status: 200,
+ body: "[]",
+ headers: { "content-type" => "application/json" }
+ )
+ stub_request(:get, url + "my-single/setup.py?ref=sha")
+ .with(headers: { "Authorization" => "token token" })
+ .to_return(
+ status: 200,
+ body: fixture("github", "setup_content.json"),
+ headers: { "content-type" => "application/json" }
+ )
+ stub_request(:get, url + "my-single/setup.cfg?ref=sha")
+ .with(headers: { "Authorization" => "token token" })
+ .to_return(status: 404)
+ stub_request(:get, url + "my-single?ref=sha")
+ .with(headers: { "Authorization" => "token token" })
+ .to_return(
+ status: 200,
+ body: "[]",
+ headers: { "content-type" => "application/json" }
+ )
+ stub_request(:get, url + "my-other/setup.py?ref=sha")
+ .with(headers: { "Authorization" => "token token" })
+ .to_return(
+ status: 200,
+ body: fixture("github", "setup_content.json"),
+ headers: { "content-type" => "application/json" }
+ )
+ stub_request(:get, url + "my-other/setup.cfg?ref=sha")
+ .with(headers: { "Authorization" => "token token" })
+ .to_return(
+ status: 200,
+ body: fixture("github", "setup_content.json"),
+ headers: { "content-type" => "application/json" }
+ )
+ stub_request(:get, url + "some/zip-file.tar.gz?ref=sha")
+ .with(headers: { "Authorization" => "token token" })
+ .to_return(
+ status: 200,
+ body: fixture("github", "setup_content.json"),
+ headers: { "content-type" => "application/json" }
+ )
+ stub_request(:get, url + "file:./setup.py?ref=sha")
+ .with(headers: { "Authorization" => "token token" })
+ .to_return(status: 404)
+ stub_request(:get, url + "my/pyproject.toml?ref=sha")
+ .with(headers: { "Authorization" => "token token" })
+ .to_return(
+ status: 200,
+ body: fixture("github", "contents_python_pyproject.json"),
+ headers: { "content-type" => "application/json" }
+ )
+ stub_request(:get, url + "my-single/pyproject.toml?ref=sha")
+ .with(headers: { "Authorization" => "token token" })
+ .to_return(
+ status: 200,
+ body: fixture("github", "contents_python_pyproject.json"),
+ headers: { "content-type" => "application/json" }
+ )
+ stub_request(:get, url + "my-other/pyproject.toml?ref=sha")
+ .with(headers: { "Authorization" => "token token" })
+ .to_return(
+ status: 200,
+ body: fixture("github", "contents_python_pyproject.json"),
+ headers: { "content-type" => "application/json" }
+ )
+ end
+
+ it "fetches the path dependencies" do
+ expect(file_fetcher_instance.files.map(&:name))
+ .to match_array(
+ %w(requirements.txt pyproject.toml my/pyproject.toml my-single/pyproject.toml
+ my-other/pyproject.toml some/zip-file.tar.gz)
+ )
+ end
+ end
+
+ context "when in a child requirement file" do
+ before do
+ stub_request(:get, url + "requirements.txt?ref=sha")
+ .with(headers: { "Authorization" => "token token" })
+ .to_return(
+ status: 200,
+ body: fixture("github", "requirements_with_cascade.json"),
+ headers: { "content-type" => "application/json" }
+ )
+ stub_request(:get, url + "more_requirements.txt?ref=sha")
+ .with(headers: { "Authorization" => "token token" })
+ .to_return(
+ status: 200,
+ body: fixture("github", "requirements_content.json"),
+ headers: { "content-type" => "application/json" }
+ )
+ stub_request(:get, url + "no_dot/more_requirements.txt?ref=sha")
+ .with(headers: { "Authorization" => "token token" })
+ .to_return(
+ status: 200,
+ body: fixture(
+ "github", "requirements_with_self_reference.json"
+ ),
+ headers: { "content-type" => "application/json" }
+ )
+ stub_request(:get, url + "comment_more_requirements.txt?ref=sha")
+ .with(headers: { "Authorization" => "token token" })
+ .to_return(
+ status: 200,
+ body: fixture("github", "requirements_content.json"),
+ headers: { "content-type" => "application/json" }
+ )
+
+ stub_request(:get, url + "no_dot?ref=sha")
+ .with(headers: { "Authorization" => "token token" })
+ .to_return(status: 200, body: repo_contents, headers: json_header)
+ stub_request(:get, url + "no_dot/setup.py?ref=sha")
+ .with(headers: { "Authorization" => "token token" })
+ .to_return(
+ status: 200,
+ body: fixture("github", "setup_content.json"),
+ headers: { "content-type" => "application/json" }
+ )
+ end
+
+ it "fetches the pyproject.toml (does not look in the nested directory)" do
+ expect(file_fetcher_instance.files.count).to eq(5)
+ expect(file_fetcher_instance.files.map(&:name))
+ .to include("pyproject.toml")
+ end
+ end
+ end
+
+ context "with a pyproject.toml and a requirements.txt file that does not use setup.py" do
+ let(:repo_contents) do
+ fixture("github", "contents_python_pyproject_and_requirements_without_setup_py.json")
+ end
+
+ before do
+ stub_request(:get, url + "requirements-test.txt?ref=sha")
+ .with(headers: { "Authorization" => "token token" })
+ .to_return(
+ status: 200,
+ body: fixture("github", "requirements_with_self_reference.json"),
+ headers: { "content-type" => "application/json" }
+ )
+ stub_request(:get, url + "pyproject.toml?ref=sha")
+ .with(headers: { "Authorization" => "token token" })
+ .to_return(
+ status: 200,
+ body: fixture("github", "contents_python_pyproject.json"),
+ headers: { "content-type" => "application/json" }
+ )
+ stub_request(:get, url + "setup.cfg?ref=sha")
+ .with(headers: { "Authorization" => "token token" })
+ .to_return(
+ status: 200,
+ body: fixture("github", "setup_cfg_content.json"),
+ headers: { "content-type" => "application/json" }
+ )
+ stub_request(:get, url + "setup.py?ref=sha")
+ .with(headers: { "Authorization" => "token token" })
+ .to_return(status: 404)
+ end
+
+ it "doesn't raise a path dependency error" do
+ expect(file_fetcher_instance.files.count).to eq(2)
+ expect(file_fetcher_instance.files.map(&:name)).to contain_exactly("requirements-test.txt", "pyproject.toml")
+ end
+ end
+
+ context "with a git dependency" do
+ let(:repo_contents) do
+ fixture("github", "contents_python_only_requirements.json")
+ end
+ let(:requirements_contents) do
+ fixture("github", "requirements_with_git_reference.json")
+ end
+
+ before do
+ stub_request(:get, url + "requirements.txt?ref=sha")
+ .with(headers: { "Authorization" => "token token" })
+ .to_return(
+ status: 200,
+ body: requirements_contents,
+ headers: { "content-type" => "application/json" }
+ )
+ end
+
+ it "doesn't confuse the git reference for a path reference" do
+ expect(file_fetcher_instance.files.count).to eq(1)
+ expect(file_fetcher_instance.files.first.name).to eq("requirements.txt")
+ end
+
+ context "when using a git URL" do
+ let(:requirements_contents) do
+ fixture("github", "requirements_with_git_url_reference.json")
+ end
+
+ it "doesn't confuse the git reference for a path reference" do
+ expect(file_fetcher_instance.files.count).to eq(1)
+ expect(file_fetcher_instance.files.first.name)
+ .to eq("requirements.txt")
+ end
+ end
+ end
+
+ context "with a very large requirements.txt file" do
+ let(:repo_contents) do
+ fixture("github", "contents_python_large_requirements_txt.json")
+ end
+
+ it "raises a Dependabot::DependencyFileNotFound error" do
+ expect { file_fetcher_instance.files }
+ .to raise_error(Dependabot::DependencyFileNotFound)
+ end
+ end
+ end
+end
diff --git a/uv/spec/dependabot/uv/file_parser/pipfile_files_parser_spec.rb b/uv/spec/dependabot/uv/file_parser/pipfile_files_parser_spec.rb
new file mode 100644
index 00000000000..b22b726b456
--- /dev/null
+++ b/uv/spec/dependabot/uv/file_parser/pipfile_files_parser_spec.rb
@@ -0,0 +1,469 @@
+# typed: false
+# frozen_string_literal: true
+
+require "spec_helper"
+require "dependabot/dependency_file"
+require "dependabot/uv/file_parser/pipfile_files_parser"
+
+RSpec.describe Dependabot::Uv::FileParser::PipfileFilesParser do
+ let(:parser) { described_class.new(dependency_files: files) }
+ let(:files) { [pipfile, lockfile] }
+
+ let(:pipfile) do
+ Dependabot::DependencyFile.new(name: "Pipfile", content: pipfile_body)
+ end
+ let(:lockfile) do
+ Dependabot::DependencyFile.new(name: "Pipfile.lock", content: lockfile_body)
+ end
+ let(:pipfile_body) { fixture("pipfile_files", pipfile_fixture_name) }
+ let(:lockfile_body) { fixture("pipfile_files", lockfile_fixture_name) }
+ let(:pipfile_fixture_name) { "version_not_specified" }
+ let(:lockfile_fixture_name) { "version_not_specified.lock" }
+
+ describe "dependency_set" do
+ subject(:dependencies) { parser.dependency_set.dependencies }
+
+ its(:length) { is_expected.to eq(7) }
+
+ describe "top level dependencies" do
+ subject(:dependencies) do
+ parser.dependency_set.dependencies.select(&:top_level?)
+ end
+
+ its(:length) { is_expected.to eq(2) }
+
+ describe "the first dependency" do
+ subject { dependencies.first }
+
+ let(:expected_requirements) do
+ [{
+ requirement: "*",
+ file: "Pipfile",
+ source: nil,
+ groups: ["default"]
+ }]
+ end
+
+ it { is_expected.to be_a(Dependabot::Dependency) }
+ its(:name) { is_expected.to eq("requests") }
+ its(:version) { is_expected.to eq("2.18.0") }
+ its(:requirements) { is_expected.to eq(expected_requirements) }
+ end
+ end
+
+ describe "sub-dependencies" do
+ subject(:dependencies) do
+ parser.dependency_set.dependencies.reject(&:top_level?)
+ end
+
+ its(:length) { is_expected.to eq(5) }
+
+ describe "the first dependency" do
+ subject { dependencies.first }
+
+ it { is_expected.to be_a(Dependabot::Dependency) }
+ its(:name) { is_expected.to eq("certifi") }
+ its(:version) { is_expected.to eq("2017.11.5") }
+ its(:requirements) { is_expected.to eq([]) }
+
+ its(:subdependency_metadata) do
+ is_expected.to eq([{ production: true }])
+ end
+ end
+
+ describe "a development only dependency" do
+ subject { dependencies.find { |d| d.name == "py" } }
+
+ its(:subdependency_metadata) do
+ is_expected.to eq([{ production: false }])
+ end
+ end
+
+ describe "a development and production dependency" do
+ subject { dependencies.find { |d| d.name == "py" } }
+
+ let(:pipfile_fixture_name) { "prod_and_dev" }
+ let(:lockfile_fixture_name) { "prod_and_dev.lock" }
+
+ its(:subdependency_metadata) do
+ is_expected.to eq([{ production: true }, { production: false }])
+ end
+ end
+ end
+
+ context "with a version specified" do
+ let(:pipfile_fixture_name) { "exact_version" }
+ let(:lockfile_fixture_name) { "exact_version.lock" }
+
+ its(:length) { is_expected.to eq(11) }
+
+ describe "top level dependencies" do
+ subject(:dependencies) do
+ parser.dependency_set.dependencies.select(&:top_level?)
+ end
+
+ its(:length) { is_expected.to eq(2) }
+
+ describe "the last dependency" do
+ subject { dependencies.last }
+
+ let(:expected_requirements) do
+ [{
+ requirement: "==3.4.0",
+ file: "Pipfile",
+ source: nil,
+ groups: ["develop"]
+ }]
+ end
+
+ it { is_expected.to be_a(Dependabot::Dependency) }
+ its(:name) { is_expected.to eq("pytest") }
+ its(:version) { is_expected.to eq("3.4.0") }
+ its(:requirements) { is_expected.to eq(expected_requirements) }
+ end
+ end
+
+ context "without a source" do
+ let(:pipfile_fixture_name) { "no_source" }
+
+ its(:length) { is_expected.to eq(11) }
+ end
+
+ context "when using arbitrary equality" do
+ let(:pipfile_fixture_name) { "arbitrary_equality" }
+ let(:lockfile_fixture_name) { "arbitrary_equality.lock" }
+
+ describe "top level dependencies" do
+ subject(:dependencies) do
+ parser.dependency_set.dependencies.select(&:top_level?)
+ end
+
+ describe "the last dependency" do
+ subject { dependencies.last }
+
+ let(:expected_requirements) do
+ [{
+ requirement: "===3.4.0",
+ file: "Pipfile",
+ source: nil,
+ groups: ["develop"]
+ }]
+ end
+
+ it { is_expected.to be_a(Dependabot::Dependency) }
+ its(:name) { is_expected.to eq("pytest") }
+ its(:version) { is_expected.to eq("3.4.0") }
+ its(:requirements) { is_expected.to eq(expected_requirements) }
+ end
+ end
+ end
+ end
+
+ context "with only dev dependencies" do
+ let(:pipfile_fixture_name) { "only_dev" }
+ let(:lockfile_fixture_name) { "only_dev.lock" }
+
+ its(:length) { is_expected.to eq(2) }
+
+ describe "top level dependencies" do
+ subject(:dependencies) do
+ parser.dependency_set.dependencies.select(&:top_level?)
+ end
+
+ its(:length) { is_expected.to eq(1) }
+
+ describe "the last dependency" do
+ subject { dependencies.first }
+
+ let(:expected_requirements) do
+ [{
+ requirement: "*",
+ file: "Pipfile",
+ source: nil,
+ groups: ["develop"]
+ }]
+ end
+
+ it { is_expected.to be_a(Dependabot::Dependency) }
+ its(:name) { is_expected.to eq("pytest") }
+ its(:version) { is_expected.to eq("3.2.3") }
+ its(:requirements) { is_expected.to eq(expected_requirements) }
+ end
+ end
+ end
+
+ context "with dependency names that need normalising" do
+ let(:pipfile_fixture_name) { "hard_names" }
+ let(:lockfile_fixture_name) { "hard_names.lock" }
+
+ describe "top level dependencies" do
+ subject(:dependencies) do
+ parser.dependency_set.dependencies.select(&:top_level?)
+ end
+
+ # NOTE: This is a bug in Pipenv! The name `discord.py` is not being
+ # properly normalised in the `Pipfile.lock`. Should be 4 once fixed.
+ its(:length) { is_expected.to eq(3) }
+
+ describe "the first dependency" do
+ subject { dependencies.first }
+
+ let(:expected_requirements) do
+ [{
+ requirement: "==2.18.0",
+ file: "Pipfile",
+ source: nil,
+ groups: ["default"]
+ }]
+ end
+
+ it { is_expected.to be_a(Dependabot::Dependency) }
+ its(:name) { is_expected.to eq("requests") }
+ its(:version) { is_expected.to eq("2.18.0") }
+ its(:requirements) { is_expected.to eq(expected_requirements) }
+ end
+ end
+ end
+
+ context "with the version specified in a hash" do
+ let(:pipfile_fixture_name) { "version_hash" }
+ let(:lockfile_fixture_name) { "version_hash.lock" }
+
+ describe "top level dependencies" do
+ subject(:dependencies) do
+ parser.dependency_set.dependencies.select(&:top_level?)
+ end
+
+ its(:length) { is_expected.to eq(2) }
+
+ describe "the first dependency" do
+ subject { dependencies.first }
+
+ let(:expected_requirements) do
+ [{
+ requirement: "==2.18.0",
+ file: "Pipfile",
+ source: nil,
+ groups: ["default"]
+ }]
+ end
+
+ it { is_expected.to be_a(Dependabot::Dependency) }
+ its(:name) { is_expected.to eq("requests") }
+ its(:version) { is_expected.to eq("2.18.0") }
+ its(:requirements) { is_expected.to eq(expected_requirements) }
+ end
+ end
+ end
+
+ context "with the version specified in a declaration table" do
+ let(:pipfile_fixture_name) { "version_table" }
+ let(:lockfile_fixture_name) { "version_hash.lock" }
+
+ describe "top level dependencies" do
+ subject(:dependencies) do
+ parser.dependency_set.dependencies.select(&:top_level?)
+ end
+
+ its(:length) { is_expected.to eq(2) }
+
+ describe "the first dependency" do
+ subject { dependencies.first }
+
+ let(:expected_requirements) do
+ [{
+ requirement: "==2.18.0",
+ file: "Pipfile",
+ source: nil,
+ groups: ["default"]
+ }]
+ end
+
+ it { is_expected.to be_a(Dependabot::Dependency) }
+ its(:name) { is_expected.to eq("requests") }
+ its(:version) { is_expected.to eq("2.18.0") }
+ its(:requirements) { is_expected.to eq(expected_requirements) }
+ end
+ end
+ end
+
+ context "with a Pipfile that isn't parseable" do
+ let(:pipfile_fixture_name) { "unparseable" }
+
+ it "raises a Dependabot::DependencyFileNotParseable error" do
+ expect { parser.dependency_set }
+ .to raise_error(Dependabot::DependencyFileNotParseable) do |error|
+ expect(error.file_name).to eq("Pipfile")
+ end
+ end
+ end
+
+ context "with a Pipfile.lock that isn't parseable" do
+ let(:lockfile_fixture_name) { "unparseable.lock" }
+
+ it "raises a Dependabot::DependencyFileNotParseable error" do
+ expect { parser.dependency_set }
+ .to raise_error(Dependabot::DependencyFileNotParseable) do |error|
+ expect(error.file_name).to eq("Pipfile.lock")
+ end
+ end
+ end
+
+ context "with no entry in the Pipfile.lock" do
+ let(:pipfile_fixture_name) { "not_in_lockfile" }
+ let(:lockfile_fixture_name) { "only_dev.lock" }
+
+ it "excludes the missing dependency" do
+ expect(dependencies.map(&:name)).not_to include("missing")
+ end
+
+ describe "the dependency" do
+ subject { dependencies.find { |d| d.name == "pytest" } }
+
+ let(:expected_requirements) do
+ [{
+ requirement: "*",
+ file: "Pipfile",
+ source: nil,
+ groups: ["develop"]
+ }]
+ end
+
+ it { is_expected.to be_a(Dependabot::Dependency) }
+ its(:name) { is_expected.to eq("pytest") }
+ its(:version) { is_expected.to eq("3.2.3") }
+ its(:requirements) { is_expected.to eq(expected_requirements) }
+ end
+ end
+
+ context "with a git source" do
+ let(:pipfile_fixture_name) { "git_source" }
+ let(:lockfile_fixture_name) { "git_source.lock" }
+
+ it "excludes the git dependency" do
+ expect(dependencies.map(&:name)).not_to include("pythonfinder")
+ end
+
+ describe "the (non-git) dependency" do
+ subject { dependencies.find { |d| d.name == "requests" } }
+
+ let(:expected_requirements) do
+ [{
+ requirement: "*",
+ file: "Pipfile",
+ source: nil,
+ groups: ["default"]
+ }]
+ end
+
+ it { is_expected.to be_a(Dependabot::Dependency) }
+ its(:name) { is_expected.to eq("requests") }
+ its(:version) { is_expected.to eq("2.18.4") }
+ its(:requirements) { is_expected.to eq(expected_requirements) }
+ end
+ end
+
+ context "with a lockfile that has been edited" do
+ # This lockfile has been edited to have a string version for requests
+ # (rather than a hash) and an array of garbage as the version for one
+ # of the subdependencies. The formed is allowed through, the later is
+ # excluded.
+ let(:lockfile_fixture_name) { "edited.lock" }
+
+ its(:length) { is_expected.to eq(6) }
+
+ describe "top level dependencies" do
+ subject(:dependencies) do
+ parser.dependency_set.dependencies.select(&:top_level?)
+ end
+
+ its(:length) { is_expected.to eq(1) }
+
+ describe "the first dependency" do
+ subject { dependencies.first }
+
+ let(:expected_requirements) do
+ [{
+ requirement: "*",
+ file: "Pipfile",
+ source: nil,
+ groups: ["default"]
+ }]
+ end
+
+ it { is_expected.to be_a(Dependabot::Dependency) }
+ its(:name) { is_expected.to eq("requests") }
+ its(:version) { is_expected.to eq("2.18.0") }
+ its(:requirements) { is_expected.to eq(expected_requirements) }
+ end
+ end
+ end
+
+ context "without a lockfile" do
+ let(:files) { [pipfile] }
+
+ its(:length) { is_expected.to eq(2) }
+
+ describe "top level dependencies" do
+ subject(:dependencies) do
+ parser.dependency_set.dependencies.select(&:top_level?)
+ end
+
+ its(:length) { is_expected.to eq(2) }
+
+ describe "the first dependency" do
+ subject { dependencies.first }
+
+ let(:expected_requirements) do
+ [{
+ requirement: "*",
+ file: "Pipfile",
+ source: nil,
+ groups: ["default"]
+ }]
+ end
+
+ it { is_expected.to be_a(Dependabot::Dependency) }
+ its(:name) { is_expected.to eq("requests") }
+ its(:version) { is_expected.to be_nil }
+ its(:requirements) { is_expected.to eq(expected_requirements) }
+
+ context "with exact versions specified in the Pipfile" do
+ let(:pipfile_fixture_name) { "exact_version" }
+
+ its(:version) { is_expected.to eq("2.18.0") }
+ end
+
+ context "with wildcard versions specified in the Pipfile" do
+ let(:pipfile_fixture_name) { "wildcard" }
+
+ its(:version) { is_expected.to be_nil }
+ end
+ end
+ end
+ end
+
+ context "with an empty requirement string" do
+ subject { dependencies.find { |d| d.name == "tensorflow-gpu" } }
+
+ let(:pipfile_fixture_name) { "empty_requirement" }
+ let(:files) { [pipfile] }
+ let(:dependencies) do
+ parser.dependency_set.dependencies.select(&:top_level?)
+ end
+
+ let(:expected_requirements) do
+ [{
+ requirement: "*",
+ file: "Pipfile",
+ source: nil,
+ groups: ["develop"]
+ }]
+ end
+
+ it { is_expected.to be_a(Dependabot::Dependency) }
+ its(:name) { is_expected.to eq("tensorflow-gpu") }
+ its(:requirements) { is_expected.to eq(expected_requirements) }
+ end
+ end
+end
diff --git a/uv/spec/dependabot/uv/file_parser/pyproject_files_parser_spec.rb b/uv/spec/dependabot/uv/file_parser/pyproject_files_parser_spec.rb
new file mode 100644
index 00000000000..2ea613186a9
--- /dev/null
+++ b/uv/spec/dependabot/uv/file_parser/pyproject_files_parser_spec.rb
@@ -0,0 +1,405 @@
+# typed: false
+# frozen_string_literal: true
+
+require "spec_helper"
+require "dependabot/dependency_file"
+require "dependabot/uv"
+
+RSpec.describe Dependabot::Uv::FileParser::PyprojectFilesParser do
+ let(:parser) { described_class.new(dependency_files: files) }
+
+ let(:files) { [pyproject] }
+ let(:pyproject) do
+ Dependabot::DependencyFile.new(
+ name: "pyproject.toml",
+ content: pyproject_body
+ )
+ end
+ let(:pyproject_body) do
+ fixture("pyproject_files", pyproject_fixture_name)
+ end
+
+ describe "parse poetry files" do
+ subject(:dependencies) { parser.dependency_set.dependencies }
+
+ let(:pyproject_fixture_name) { "basic_poetry_dependencies.toml" }
+
+ context "when defined incorrectly" do
+ let(:pyproject_fixture_name) { "incorrect_poetry_setup.toml" }
+
+ it "raises a DependencyFileNotParseable error" do
+ expect { parser.dependency_set }
+ .to raise_error do |error|
+ expect(error.class)
+ .to eq(Dependabot::DependencyFileNotParseable)
+ # rubocop:disable Style/RedundantStringEscape
+ expect(error.message)
+ .to eq <<~ERROR.strip
+ \/pyproject.toml is missing the following sections:
+ * tool.poetry.name
+ * tool.poetry.version
+ * tool.poetry.description
+ * tool.poetry.authors
+ ERROR
+ # rubocop:enable Style/RedundantStringEscape
+ end
+ end
+ end
+
+ context "without a lockfile" do
+ its(:length) { is_expected.to eq(15) }
+
+ it "doesn't include the Python requirement" do
+ expect(dependencies.map(&:name)).not_to include("python")
+ end
+
+ context "with a string declaration" do
+ subject(:dependency) { dependencies.first }
+
+ it "has the right details" do
+ expect(dependency).to be_a(Dependabot::Dependency)
+ expect(dependency.name).to eq("geopy")
+ expect(dependency.version).to be_nil
+ expect(dependency.requirements).to eq(
+ [{
+ requirement: "^1.13",
+ file: "pyproject.toml",
+ groups: ["dependencies"],
+ source: nil
+ }]
+ )
+ end
+ end
+
+ context "with an invalid requirement" do
+ let(:pyproject_fixture_name) { "invalid_wildcard.toml" }
+
+ it "raises a helpful error" do
+ expect { parser.dependency_set }
+ .to raise_error do |error|
+ expect(error.class)
+ .to eq(Dependabot::DependencyFileNotEvaluatable)
+ expect(error.message)
+ .to eq('Illformed requirement ["2.18.^"]')
+ end
+ end
+ end
+
+ context "with a path requirement" do
+ subject(:dependency_names) { dependencies.map(&:name) }
+
+ let(:pyproject_fixture_name) { "dir_dependency.toml" }
+
+ it "excludes path dependency" do
+ expect(dependency_names).not_to include("toml")
+ end
+
+ it "includes non-path dependencies" do
+ expect(dependency_names).to include("pytest")
+ end
+ end
+
+ context "with a git requirement" do
+ subject(:dependency_names) { dependencies.map(&:name) }
+
+ let(:pyproject_fixture_name) { "git_dependency.toml" }
+
+ it "excludes git dependency" do
+ expect(dependency_names).not_to include("toml")
+ end
+
+ it "includes non-git dependencies" do
+ expect(dependency_names).to include("pytest")
+ end
+ end
+
+ context "with a url requirement" do
+ subject(:dependency_names) { dependencies.map(&:name) }
+
+ let(:pyproject_fixture_name) { "url_dependency.toml" }
+
+ it "excludes url dependency" do
+ expect(dependency_names).not_to include("toml")
+ end
+
+ it "includes non-url dependencies" do
+ expect(dependency_names).to include("pytest")
+ end
+ end
+
+ context "with non-package mode" do
+ let(:pyproject_fixture_name) { "poetry_non_package_mode.toml" }
+
+ it "parses correctly with no metadata" do
+ expect { parser.dependency_set }.not_to raise_error
+ end
+ end
+ end
+
+ context "with a lockfile" do
+ let(:files) { [pyproject, poetry_lock] }
+ let(:poetry_lock) do
+ Dependabot::DependencyFile.new(
+ name: "poetry.lock",
+ content: poetry_lock_body
+ )
+ end
+ let(:poetry_lock_body) do
+ fixture("poetry_locks", poetry_lock_fixture_name)
+ end
+ let(:poetry_lock_fixture_name) { "poetry.lock" }
+
+ its(:length) { is_expected.to eq(36) }
+
+ it "doesn't include the Python requirement" do
+ expect(dependencies.map(&:name)).not_to include("python")
+ end
+
+ describe "a development sub-dependency" do
+ subject(:dep) { dependencies.find { |d| d.name == "atomicwrites" } }
+
+ its(:subdependency_metadata) do
+ is_expected.to eq([{ production: false }])
+ end
+ end
+
+ describe "a production sub-dependency" do
+ subject(:dep) { dependencies.find { |d| d.name == "certifi" } }
+
+ its(:subdependency_metadata) do
+ is_expected.to eq([{ production: true }])
+ end
+ end
+
+ context "with a path dependency" do
+ subject(:dependency_names) { dependencies.map(&:name) }
+
+ let(:pyproject_fixture_name) { "dir_dependency.toml" }
+ let(:poetry_lock_fixture_name) { "dir_dependency.lock" }
+
+ it "excludes the path dependency" do
+ expect(dependency_names).not_to include("toml")
+ end
+
+ it "includes non-path dependencies" do
+ expect(dependency_names).to include("pytest")
+ end
+ end
+
+ context "with a git dependency" do
+ let(:pyproject_fixture_name) { "git_dependency.toml" }
+ let(:poetry_lock_fixture_name) { "git_dependency.lock" }
+
+ it "excludes the git dependency" do
+ expect(dependencies.map(&:name)).not_to include("toml")
+ end
+ end
+
+ context "with a url dependency" do
+ let(:pyproject_fixture_name) { "url_dependency.toml" }
+ let(:poetry_lock_fixture_name) { "url_dependency.lock" }
+
+ it "excludes the url dependency" do
+ expect(dependencies.map(&:name)).not_to include("toml")
+ end
+ end
+
+ context "with a manifest declaration" do
+ subject(:dependency) { dependencies.find { |f| f.name == "geopy" } }
+
+ it "has the right details" do
+ expect(dependency).to be_a(Dependabot::Dependency)
+ expect(dependency.name).to eq("geopy")
+ expect(dependency.version).to eq("1.14.0")
+ expect(dependency.requirements).to eq(
+ [{
+ requirement: "^1.13",
+ file: "pyproject.toml",
+ groups: ["dependencies"],
+ source: nil
+ }]
+ )
+ end
+
+ context "when having a name that needs normalising" do
+ subject(:dependency) { dependencies.find { |f| f.name == "pillow" } }
+
+ it "has the right details" do
+ expect(dependency).to be_a(Dependabot::Dependency)
+ expect(dependency.name).to eq("pillow")
+ expect(dependency.version).to eq("5.1.0")
+ expect(dependency.requirements).to eq(
+ [{
+ requirement: "^5.1",
+ file: "pyproject.toml",
+ groups: ["dependencies"],
+ source: nil
+ }]
+ )
+ end
+ end
+ end
+
+ context "without a manifest declaration" do
+ subject(:dependency) { dependencies.find { |f| f.name == "appdirs" } }
+
+ it "has the right details" do
+ expect(dependency).to be_a(Dependabot::Dependency)
+ expect(dependency.name).to eq("appdirs")
+ expect(dependency.version).to eq("1.4.3")
+ expect(dependency.requirements).to eq([])
+ end
+ end
+ end
+
+ context "with group dependencies" do
+ subject(:dependency_names) { dependencies.map(&:name) }
+
+ let(:pyproject_fixture_name) { "poetry_group_dependencies.toml" }
+
+ it "includes dev-dependencies and group.dev.dependencies" do
+ expect(dependency_names).to include("black")
+ expect(dependency_names).to include("pytest")
+ end
+
+ it "includes other group dependencies" do
+ expect(dependency_names).to include("sphinx")
+ end
+ end
+
+ context "with package specify source" do
+ subject(:dependency) { dependencies.find { |f| f.name == "black" } }
+
+ let(:pyproject_fixture_name) { "package_specify_source.toml" }
+
+ it "specifies a package source" do
+ expect(dependency.requirements[0][:source]).to eq("custom")
+ end
+ end
+ end
+
+ describe "parse standard python files" do
+ subject(:dependencies) { parser.dependency_set.dependencies }
+
+ let(:pyproject_fixture_name) { "standard_python.toml" }
+
+ # fixture has 1 build system requires and plus 1 dependencies exists
+
+ its(:length) { is_expected.to eq(2) }
+
+ context "with a string declaration" do
+ subject(:dependency) { dependencies.first }
+
+ it "has the right details" do
+ expect(dependency).to be_a(Dependabot::Dependency)
+ expect(dependency.name).to eq("ansys-templates")
+ expect(dependency.version).to eq("0.3.0")
+ expect(dependency.requirements).to eq(
+ [{
+ requirement: "==0.3.0",
+ file: "pyproject.toml",
+ groups: [],
+ source: nil
+ }]
+ )
+ expect(dependency).to be_production
+ end
+ end
+
+ context "without dependencies" do
+ subject(:dependencies) { parser.dependency_set.dependencies }
+
+ let(:pyproject_fixture_name) { "no_dependencies.toml" }
+
+ # fixture has 1 build system requires and no dependencies or
+ # optional dependencies exists
+
+ its(:length) { is_expected.to eq(1) }
+ end
+
+ context "with dependencies with empty requirements" do
+ subject(:dependencies) { parser.dependency_set.dependencies }
+
+ let(:pyproject_fixture_name) { "no_requirements.toml" }
+
+ its(:length) { is_expected.to eq(0) }
+ end
+
+ context "with a PDM project" do
+ subject(:dependencies) { parser.dependency_set.dependencies }
+
+ let(:pyproject_fixture_name) { "pdm_example.toml" }
+ let(:pdm_lock) do
+ Dependabot::DependencyFile.new(
+ name: "pdm.lock",
+ content: pdm_lock_body
+ )
+ end
+ let(:pdm_lock_body) do
+ fixture("poetry_locks", poetry_lock_fixture_name)
+ end
+ let(:poetry_lock_fixture_name) { "pdm_example.lock" }
+ let(:files) { [pyproject, pdm_lock] }
+
+ its(:length) { is_expected.to eq(0) }
+
+ context "when a leftover poetry.lock is present" do
+ let(:poetry_lock) do
+ Dependabot::DependencyFile.new(
+ name: "poetry.lock",
+ content: poetry_lock_body
+ )
+ end
+ let(:poetry_lock_body) do
+ fixture("poetry_locks", poetry_lock_fixture_name)
+ end
+ let(:poetry_lock_fixture_name) { "poetry.lock" }
+
+ let(:files) { [pyproject, pdm_lock, poetry_lock] }
+
+ its(:length) { is_expected.to eq(0) }
+ end
+ end
+
+ context "with optional dependencies" do
+ subject(:dependencies) { parser.dependency_set.dependencies }
+
+ let(:pyproject_fixture_name) { "optional_dependencies.toml" }
+
+ # fixture has 1 runtime dependency, plus 4 optional dependencies, but one
+ # is ignored because it has markers, plus 1 is build system requires
+ its(:length) { is_expected.to eq(5) }
+ end
+
+ describe "parse standard python files" do
+ subject(:dependencies) { parser.dependency_set.dependencies }
+
+ let(:pyproject_fixture_name) { "pyproject_1_0_0.toml" }
+
+ # fixture has 1 build system requires and plus 1 dependencies exists
+
+ its(:length) { is_expected.to eq(1) }
+
+ context "with a string declaration" do
+ subject(:dependency) { dependencies.first }
+
+ it "has the right details" do
+ expect(dependency).to be_a(Dependabot::Dependency)
+ expect(dependency.name).to eq("pydantic")
+ expect(dependency.version).to eq("2.7.0")
+ end
+ end
+
+ context "without dependencies" do
+ subject(:dependencies) { parser.dependency_set.dependencies }
+
+ let(:pyproject_fixture_name) { "pyproject_1_0_0_nodeps.toml" }
+
+ # fixture has 1 build system requires and no dependencies or
+ # optional dependencies exists
+
+ its(:length) { is_expected.to eq(0) }
+ end
+ end
+ end
+end
diff --git a/uv/spec/dependabot/uv/file_parser/python_requirement_parser_spec.rb b/uv/spec/dependabot/uv/file_parser/python_requirement_parser_spec.rb
new file mode 100644
index 00000000000..2fc6aeeb7bb
--- /dev/null
+++ b/uv/spec/dependabot/uv/file_parser/python_requirement_parser_spec.rb
@@ -0,0 +1,99 @@
+# typed: false
+# frozen_string_literal: true
+
+require "spec_helper"
+require "dependabot/dependency_file"
+require "dependabot/uv/file_parser/python_requirement_parser"
+
+RSpec.describe Dependabot::Uv::FileParser::PythonRequirementParser do
+ let(:parser) { described_class.new(dependency_files: files) }
+
+ describe "#user_specified_requirements" do
+ subject(:user_specified_requirements) { parser.user_specified_requirements }
+
+ context "with pip compile files" do
+ let(:files) { [in_file, txt_file] }
+ let(:in_file) do
+ Dependabot::DependencyFile.new(
+ name: "requirements.in",
+ content: fixture("pip_compile_files", "python_header.in")
+ )
+ end
+ let(:txt_file) do
+ Dependabot::DependencyFile.new(
+ name: "requirements.txt",
+ content: fixture("requirements", fixture_name)
+ )
+ end
+ let(:fixture_name) { "python_header.txt" }
+
+ it { is_expected.to eq(["3.8"]) }
+
+ context "with lowercase header" do
+ let(:fixture_name) { "python_header_lower.txt" }
+
+ it { is_expected.to eq(["3.8"]) }
+ end
+ end
+
+ context "with a .python-version file" do
+ let(:files) { [python_version_file] }
+ let(:python_version_file) do
+ Dependabot::DependencyFile.new(
+ name: ".python-version",
+ content: python_version_body
+ )
+ end
+ let(:python_version_body) { "3.6.2\n" }
+
+ it { is_expected.to eq(["3.6.2"]) }
+
+ context "when having a version unknown to pyenv" do
+ let(:python_version_body) { "personal-3.6.2\n" }
+
+ it { is_expected.to eq([]) }
+ end
+
+ context "when the file contains comments" do
+ let(:python_version_body) { "# this is a comment\n3.6.2" }
+
+ it { is_expected.to eq(["3.6.2"]) }
+ end
+
+ context "when the file contains inline comments" do
+ let(:python_version_body) { "3.6.2 # this is a comment" }
+
+ it { is_expected.to eq(["3.6.2"]) }
+ end
+ end
+
+ context "with a setup.py file" do
+ let(:files) { [setup_py] }
+ let(:setup_py) do
+ Dependabot::DependencyFile.new(
+ name: "setup.py",
+ content: setup_py_body
+ )
+ end
+ let(:setup_py_body) { fixture("setup_files", fixture_name) }
+
+ context "when including a python_requires line" do
+ let(:fixture_name) { "impossible_imports.py" }
+
+ it { is_expected.to eq([">=3.7"]) }
+ end
+
+ context "when not including a python_requires line" do
+ let(:fixture_name) { "setup.py" }
+
+ it { is_expected.to eq([]) }
+ end
+
+ context "when having a requirement that can't be parsed" do
+ let(:fixture_name) { "unparseable_python_requires.py" }
+
+ it { is_expected.to eq([]) }
+ end
+ end
+ end
+end
diff --git a/uv/spec/dependabot/uv/file_parser/setup_file_parser_spec.rb b/uv/spec/dependabot/uv/file_parser/setup_file_parser_spec.rb
new file mode 100644
index 00000000000..6f9288b62b8
--- /dev/null
+++ b/uv/spec/dependabot/uv/file_parser/setup_file_parser_spec.rb
@@ -0,0 +1,293 @@
+# typed: false
+# frozen_string_literal: true
+
+require "spec_helper"
+require "dependabot/dependency_file"
+require "dependabot/uv/file_parser/setup_file_parser"
+
+RSpec.describe Dependabot::Uv::FileParser::SetupFileParser do
+ let(:parser) { described_class.new(dependency_files: files) }
+
+ describe "for setup.py" do
+ let(:files) { [setup_file] }
+ let(:setup_file) do
+ Dependabot::DependencyFile.new(
+ name: "setup.py",
+ content: setup_file_body
+ )
+ end
+ let(:setup_file_body) do
+ fixture("setup_files", setup_file_fixture_name)
+ end
+ let(:setup_file_fixture_name) { "setup.py" }
+
+ describe "parse" do
+ subject(:dependencies) { parser.dependency_set.dependencies }
+
+ its(:length) { is_expected.to eq(15) }
+
+ describe "an install_requires dependencies" do
+ subject(:dependency) { dependencies.find { |d| d.name == "boto3" } }
+
+ it "has the right details" do
+ expect(dependency).to be_a(Dependabot::Dependency)
+ expect(dependency.name).to eq("boto3")
+ expect(dependency.version).to eq("1.3.1")
+ expect(dependency.requirements).to eq(
+ [{
+ requirement: "==1.3.1",
+ file: "setup.py",
+ groups: ["install_requires"],
+ source: nil
+ }]
+ )
+ end
+ end
+
+ describe "a setup_requires dependencies" do
+ subject(:dependency) { dependencies.find { |d| d.name == "numpy" } }
+
+ it "has the right details" do
+ expect(dependency).to be_a(Dependabot::Dependency)
+ expect(dependency.name).to eq("numpy")
+ expect(dependency.version).to eq("1.11.0")
+ expect(dependency.requirements).to eq(
+ [{
+ requirement: "==1.11.0",
+ file: "setup.py",
+ groups: ["setup_requires"],
+ source: nil
+ }]
+ )
+ end
+ end
+
+ describe "a tests_require dependencies" do
+ subject(:dependency) { dependencies.find { |d| d.name == "responses" } }
+
+ it "has the right details" do
+ expect(dependency).to be_a(Dependabot::Dependency)
+ expect(dependency.name).to eq("responses")
+ expect(dependency.version).to eq("0.5.1")
+ expect(dependency.requirements).to eq(
+ [{
+ requirement: "==0.5.1",
+ file: "setup.py",
+ groups: ["tests_require"],
+ source: nil
+ }]
+ )
+ end
+ end
+
+ describe "an extras_require dependencies" do
+ subject(:dependency) { dependencies.find { |d| d.name == "flask" } }
+
+ it "has the right details" do
+ expect(dependency).to be_a(Dependabot::Dependency)
+ expect(dependency.name).to eq("flask")
+ expect(dependency.version).to eq("0.12.2")
+ expect(dependency.requirements).to eq(
+ [{
+ requirement: "==0.12.2",
+ file: "setup.py",
+ groups: ["extras_require:API"],
+ source: nil
+ }]
+ )
+ end
+ end
+
+ context "without a `tests_require` key" do
+ let(:setup_file_fixture_name) { "no_tests_require.py" }
+
+ its(:length) { is_expected.to eq(12) }
+ end
+
+ context "with a `print` statement" do
+ let(:setup_file_fixture_name) { "with_print.py" }
+
+ its(:length) { is_expected.to eq(14) }
+ end
+
+ context "with an import statements that can't be handled" do
+ let(:setup_file_fixture_name) { "impossible_imports.py" }
+
+ its(:length) { is_expected.to eq(12) }
+ end
+
+ context "with an illformed_requirement" do
+ let(:setup_file_fixture_name) { "illformed_req.py" }
+
+ it "raises a helpful error" do
+ expect { parser.dependency_set }
+ .to raise_error do |error|
+ expect(error.class)
+ .to eq(Dependabot::DependencyFileNotEvaluatable)
+ expect(error.message)
+ .to eq('Illformed requirement ["==2.6.1raven==5.32.0"]')
+ end
+ end
+ end
+
+ context "with an `open` statement" do
+ let(:setup_file_fixture_name) { "with_open.py" }
+
+ its(:length) { is_expected.to eq(14) }
+ end
+
+ context "with the setup.py from requests" do
+ let(:setup_file_fixture_name) { "requests_setup.py" }
+
+ its(:length) { is_expected.to eq(13) }
+ end
+
+ context "with an import of a config file" do
+ let(:setup_file_fixture_name) { "imports_version.py" }
+
+ its(:length) { is_expected.to eq(14) }
+
+ context "with a inserted version" do
+ let(:setup_file_fixture_name) { "imports_version_for_dep.py" }
+
+ it "excludes the dependency importing a version" do
+ expect(dependencies.count).to eq(14)
+ expect(dependencies.map(&:name)).not_to include("acme")
+ end
+ end
+ end
+ end
+ end
+
+ describe "for setup.cfg" do
+ let(:files) { [setup_cfg_file] }
+ let(:setup_cfg_file) do
+ Dependabot::DependencyFile.new(
+ name: "setup.cfg",
+ content: setup_cfg_file_body
+ )
+ end
+ let(:setup_cfg_file_body) do
+ fixture("setup_files", setup_cfg_file_fixture_name)
+ end
+ let(:setup_cfg_file_fixture_name) { "setup_with_requires.cfg" }
+
+ describe "parse" do
+ subject(:dependencies) { parser.dependency_set.dependencies }
+
+ its(:length) { is_expected.to eq(15) }
+
+ describe "an install_requires dependencies" do
+ subject(:dependency) { dependencies.find { |d| d.name == "boto3" } }
+
+ it "has the right details" do
+ expect(dependency).to be_a(Dependabot::Dependency)
+ expect(dependency.name).to eq("boto3")
+ expect(dependency.version).to eq("1.3.1")
+ expect(dependency.requirements).to eq(
+ [{
+ requirement: "==1.3.1",
+ file: "setup.cfg",
+ groups: ["install_requires"],
+ source: nil
+ }]
+ )
+ end
+ end
+
+ describe "a setup_requires dependencies" do
+ subject(:dependency) { dependencies.find { |d| d.name == "numpy" } }
+
+ it "has the right details" do
+ expect(dependency).to be_a(Dependabot::Dependency)
+ expect(dependency.name).to eq("numpy")
+ expect(dependency.version).to eq("1.11.0")
+ expect(dependency.requirements).to eq(
+ [{
+ requirement: "==1.11.0",
+ file: "setup.cfg",
+ groups: ["setup_requires"],
+ source: nil
+ }]
+ )
+ end
+ end
+
+ describe "a tests_require dependencies" do
+ subject(:dependency) { dependencies.find { |d| d.name == "responses" } }
+
+ it "has the right details" do
+ expect(dependency).to be_a(Dependabot::Dependency)
+ expect(dependency.name).to eq("responses")
+ expect(dependency.version).to eq("0.5.1")
+ expect(dependency.requirements).to eq(
+ [{
+ requirement: "==0.5.1",
+ file: "setup.cfg",
+ groups: ["tests_require"],
+ source: nil
+ }]
+ )
+ end
+ end
+
+ describe "an extras_require dependencies" do
+ subject(:dependency) { dependencies.find { |d| d.name == "flask" } }
+
+ it "has the right details" do
+ expect(dependency).to be_a(Dependabot::Dependency)
+ expect(dependency.name).to eq("flask")
+ expect(dependency.version).to eq("0.12.2")
+ expect(dependency.requirements).to eq(
+ [{
+ requirement: "==0.12.2",
+ file: "setup.cfg",
+ groups: ["extras_require:api"],
+ source: nil
+ }]
+ )
+ end
+ end
+
+ context "without a `tests_require` key" do
+ let(:setup_cfg_file_fixture_name) { "no_tests_require.cfg" }
+
+ its(:length) { is_expected.to eq(12) }
+ end
+
+ context "with an illformed_requirement" do
+ let(:setup_cfg_file_fixture_name) { "illformed_req.cfg" }
+
+ it "raises a helpful error" do
+ expect { parser.dependency_set }
+ .to raise_error do |error|
+ expect(error.class)
+ .to eq(Dependabot::DependencyFileNotEvaluatable)
+ expect(error.message)
+ .to include("InstallationError(\"Invalid requirement: 'psycopg2==2.6.1raven == 5.32.0'\")")
+ end
+ end
+ end
+
+ context "with comments in the setup.cfg file" do
+ subject(:dependency) { dependencies.find { |d| d.name == "boto3" } }
+
+ let(:setup_cfg_file_fixture_name) { "with_comments.cfg" }
+
+ it "has the right details" do
+ expect(dependency).to be_a(Dependabot::Dependency)
+ expect(dependency.name).to eq("boto3")
+ expect(dependency.version).to eq("1.3.1")
+ expect(dependency.requirements).to eq(
+ [{
+ requirement: "==1.3.1",
+ file: "setup.cfg",
+ groups: ["install_requires"],
+ source: nil
+ }]
+ )
+ end
+ end
+ end
+ end
+end
diff --git a/uv/spec/dependabot/uv/file_parser_spec.rb b/uv/spec/dependabot/uv/file_parser_spec.rb
new file mode 100644
index 00000000000..f10041fb5fb
--- /dev/null
+++ b/uv/spec/dependabot/uv/file_parser_spec.rb
@@ -0,0 +1,859 @@
+# typed: false
+# frozen_string_literal: true
+
+require "spec_helper"
+require "dependabot/dependency_file"
+require "dependabot/source"
+require "dependabot/uv/file_parser"
+require_common_spec "file_parsers/shared_examples_for_file_parsers"
+
+RSpec.describe Dependabot::Uv::FileParser do
+ let(:requirements_fixture_name) { "version_specified.txt" }
+ let(:requirements_body) { fixture("requirements", requirements_fixture_name) }
+ let(:requirements) do
+ Dependabot::DependencyFile.new(
+ name: "requirements.txt",
+ content: requirements_body
+ )
+ end
+ let(:files) { [requirements] }
+ let(:reject_external_code) { false }
+ let(:source) do
+ Dependabot::Source.new(
+ provider: "github",
+ repo: "gocardless/bump",
+ directory: "/"
+ )
+ end
+ let(:parser) do
+ described_class.new(
+ dependency_files: files,
+ source: source,
+ reject_external_code: reject_external_code
+ )
+ end
+
+ it_behaves_like "a dependency file parser"
+
+ describe "parse" do
+ subject(:dependencies) { parser.parse }
+
+ its(:length) { is_expected.to eq(5) }
+
+ context "with a version specified" do
+ describe "the first dependency" do
+ subject(:dependency) { dependencies.first }
+
+ it "has the right details" do
+ expect(dependency).to be_a(Dependabot::Dependency)
+ expect(dependency.name).to eq("psycopg2")
+ expect(dependency.version).to eq("2.6.1")
+ expect(dependency.requirements).to eq(
+ [{
+ requirement: "==2.6.1",
+ file: "requirements.txt",
+ groups: ["dependencies"],
+ source: nil
+ }]
+ )
+ end
+ end
+ end
+
+ context "with a .python-version file" do
+ let(:files) { [requirements, python_version_file] }
+ let(:python_version_file) do
+ Dependabot::DependencyFile.new(
+ name: ".python-version",
+ content: "2.7.18\n"
+ )
+ end
+
+ its(:length) { is_expected.to eq(5) }
+ end
+
+ context "with jinja templates" do
+ let(:requirements_fixture_name) { "jinja_requirements.txt" }
+
+ it "raises a Dependabot::DependencyFileNotEvaluatable error" do
+ expect { parser.parse }
+ .to raise_error(Dependabot::DependencyFileNotEvaluatable)
+ end
+ end
+
+ context "with comments" do
+ let(:requirements_fixture_name) { "comments.txt" }
+
+ its(:length) { is_expected.to eq(2) }
+
+ describe "the first dependency" do
+ subject(:dependency) { dependencies.first }
+
+ it "has the right details" do
+ expect(dependency).to be_a(Dependabot::Dependency)
+ expect(dependency.name).to eq("psycopg2")
+ expect(dependency.version).to eq("2.6.1")
+ expect(dependency.requirements).to eq(
+ [{
+ requirement: "==2.6.1",
+ file: "requirements.txt",
+ groups: ["dependencies"],
+ source: nil
+ }]
+ )
+ end
+ end
+ end
+
+ context "with markers" do
+ context "when the marker <= 2.6" do
+ before do
+ allow(parser).to receive(:python_raw_version).and_return("2.6")
+ end
+
+ let(:requirements_fixture_name) { "markers.txt" }
+
+ it "then the dependency version should be 1.0.4" do
+ expect(dependencies.length).to eq(1)
+
+ dependency = dependencies.first
+
+ expect(dependency).to be_a(Dependabot::Dependency)
+ expect(dependency.name).to eq("distro")
+ expect(dependency.version).to eq("1.0.4")
+ expect(dependency.requirements).to eq(
+ [{
+ requirement: "==1.0.4",
+ file: "requirements.txt",
+ groups: ["dependencies"],
+ source: nil
+ }]
+ )
+ end
+ end
+
+ context "when the marker => 2.7" do
+ before do
+ allow(parser).to receive(:python_raw_version).and_return("2.7")
+ end
+
+ let(:requirements_fixture_name) { "markers.txt" }
+
+ it "then the dependency version should be 1.3.0" do
+ expect(dependencies.length).to eq(1)
+
+ dependency = dependencies.first
+
+ expect(dependency).to be_a(Dependabot::Dependency)
+ expect(dependency.name).to eq("distro")
+ expect(dependency.version).to eq("1.3.0")
+ expect(dependency.requirements).to eq(
+ [{
+ requirement: "==1.3.0",
+ file: "requirements.txt",
+ groups: ["dependencies"],
+ source: nil
+ }]
+ )
+ end
+ end
+
+ context "when there is a combination of multiple conditions with 'and' in a marker" do
+ before do
+ allow(parser).to receive(:python_raw_version).and_return("3.13.1")
+ end
+
+ # python_version >= '3.0' and python_version <= '3.7'
+ let(:requirements_fixture_name) { "markers_with_combination_of_conditions.txt" }
+
+ it "then the dependency version should be 1.3.0" do
+ expect(dependencies.length).to eq(1)
+
+ dependency = dependencies.first
+
+ expect(dependency).to be_a(Dependabot::Dependency)
+ expect(dependency.name).to eq("arrow")
+ expect(dependency.version).to eq("1.3.0")
+ expect(dependency.requirements).to eq(
+ [{
+ requirement: "==1.3.0",
+ file: "requirements.txt",
+ groups: ["dependencies"],
+ source: nil
+ }]
+ )
+ end
+ end
+
+ context "when including a < in the requirement" do
+ let(:requirements_fixture_name) { "markers_2.txt" }
+
+ it "parses only the >= marker" do
+ expect(dependencies.length).to eq(1)
+
+ dependency = dependencies.first
+
+ expect(dependency).to be_a(Dependabot::Dependency)
+ expect(dependency.name).to eq("cryptography")
+ expect(dependency.version).to eq("2.7")
+ expect(dependency.requirements).to eq(
+ [{
+ requirement: "==2.7",
+ file: "requirements.txt",
+ groups: ["dependencies"],
+ source: nil
+ }]
+ )
+ end
+ end
+
+ context "when the marker is malformed" do
+ before do
+ allow(parser).to receive(:python_raw_version).and_return("3.13.3")
+ end
+
+ let(:requirements_fixture_name) { "malformed_markers.txt" }
+
+ it "does not return any dependencies" do
+ expect(dependencies).to be_empty
+ end
+ end
+ end
+
+ context "with extras" do
+ let(:requirements_fixture_name) { "extras.txt" }
+
+ describe "the first dependency" do
+ subject(:dependency) { dependencies.first }
+
+ it "has the right details" do
+ expect(dependency).to be_a(Dependabot::Dependency)
+ expect(dependency.name).to eq("psycopg2[bar,foo]")
+ expect(dependency.version).to eq("2.6.1")
+ expect(dependency.requirements).to eq(
+ [{
+ requirement: "==2.6.1",
+ file: "requirements.txt",
+ groups: ["dependencies"],
+ source: nil
+ }]
+ )
+ end
+ end
+ end
+
+ context "with an 'unsafe' name" do
+ let(:requirements_body) { "mypy_extensions==0.2.0" }
+
+ describe "the first dependency" do
+ subject(:dependency) { dependencies.first }
+
+ it "normalises the name" do
+ expect(dependency).to be_a(Dependabot::Dependency)
+ expect(dependency.name).to eq("mypy-extensions")
+ end
+ end
+ end
+
+ context "with invalid lines" do
+ let(:requirements_fixture_name) { "invalid_lines.txt" }
+
+ it "raises a Dependabot::DependencyFileNotEvaluatable error" do
+ expect { parser.parse }
+ .to raise_error(Dependabot::DependencyFileNotEvaluatable)
+ end
+ end
+
+ context "with tarball path dependencies" do
+ let(:files) { [pyproject, requirements, tarball_path_dependency] }
+ let(:requirements) do
+ Dependabot::DependencyFile.new(
+ name: "requirements.txt",
+ content: fixture("requirements", "tarball_path_dependency")
+ )
+ end
+ let(:pyproject) do
+ Dependabot::DependencyFile.new(
+ name: "pyproject.toml",
+ content: fixture("pyproject_files", "tarball_path_dependency.toml")
+ )
+ end
+ let(:tarball_path_dependency) do
+ Dependabot::DependencyFile.new(
+ name: "taxtea-0.6.0.tar.gz",
+ content: fixture("path_dependencies", "taxtea-0.6.0.tar.gz")
+ )
+ end
+
+ describe "the tarball dependency requirement" do
+ it "is not parsed" do
+ expect(dependencies).to eq([])
+ end
+ end
+ end
+
+ context "when itself is required" do
+ let(:files) { [requirements] }
+ let(:requirements_fixture_name) { "cascading.txt" }
+ let(:requirements) do
+ Dependabot::DependencyFile.new(
+ name: "more_requirements.txt",
+ content: requirements_body
+ )
+ end
+
+ it "raises a Dependabot::DependencyFileNotEvaluatable error" do
+ expect { parser.parse }
+ .to raise_error(Dependabot::DependencyFileNotEvaluatable)
+ end
+ end
+
+ context "with an invalid value" do
+ let(:requirements_fixture_name) { "invalid_value.txt" }
+
+ it "raises a Dependabot::DependencyFileNotEvaluatable error" do
+ expect { parser.parse }
+ .to raise_error(Dependabot::DependencyFileNotEvaluatable)
+ end
+ end
+
+ context "with invalid options" do
+ let(:requirements_fixture_name) { "invalid_options.txt" }
+
+ it "raises a Dependabot::DependencyFileNotEvaluatable error" do
+ expect { parser.parse }
+ .to raise_error(Dependabot::DependencyFileNotEvaluatable)
+ end
+ end
+
+ context "with invalid requirements" do
+ let(:requirements_fixture_name) { "invalid_requirements.txt" }
+
+ it "raises a Dependabot::DependencyFileNotEvaluatable error" do
+ expect { parser.parse }
+ .to raise_error(Dependabot::DependencyFileNotEvaluatable)
+ end
+ end
+
+ context "with remote constraints" do
+ let(:requirements_fixture_name) { "remote_constraints.txt" }
+
+ its(:length) { is_expected.to eq(0) }
+ end
+
+ context "with no version specified" do
+ let(:requirements_fixture_name) { "version_not_specified.txt" }
+
+ its(:length) { is_expected.to eq(2) }
+
+ describe "the first dependency" do
+ subject(:dependency) { dependencies.first }
+
+ it "has the right details" do
+ expect(dependency).to be_a(Dependabot::Dependency)
+ expect(dependency.name).to eq("psycopg2")
+ expect(dependency.version).to be_nil
+ expect(dependency.requirements.first[:requirement]).to be_nil
+ end
+ end
+ end
+
+ context "with prefix matching specified" do
+ let(:requirements_fixture_name) { "prefix_match.txt" }
+
+ its(:length) { is_expected.to eq(2) }
+
+ describe "the first dependency" do
+ subject(:dependency) { dependencies.first }
+
+ it "has the right details" do
+ expect(dependency).to be_a(Dependabot::Dependency)
+ expect(dependency.name).to eq("psycopg2")
+ expect(dependency.version).to be_nil
+ expect(dependency.requirements.first[:requirement]).to eq("==2.6.*")
+ end
+ end
+ end
+
+ context "with a version specified as between two constraints" do
+ let(:requirements_fixture_name) { "version_between_bounds.txt" }
+
+ its(:length) { is_expected.to eq(2) }
+
+ describe "the first dependency" do
+ subject(:dependency) { dependencies.first }
+
+ it "has the right details" do
+ expect(dependency).to be_a(Dependabot::Dependency)
+ expect(dependency.name).to eq("psycopg2")
+ expect(dependency.version).to be_nil
+ expect(dependency.requirements.first[:requirement])
+ .to eq("<=3.0.0,==2.6.1")
+ end
+ end
+ end
+
+ context "with a git dependency" do
+ let(:requirements_fixture_name) { "with_git_dependency.txt" }
+
+ its(:length) { is_expected.to eq(2) }
+ end
+
+ context "with a file dependency" do
+ let(:requirements_fixture_name) { "with_path_dependency.txt" }
+
+ its(:length) { is_expected.to eq(1) }
+ end
+
+ context "with requirements-dev.txt" do
+ let(:file) { [requirements] }
+ let(:requirements) do
+ Dependabot::DependencyFile.new(
+ name: "requirements-dev.txt",
+ content: fixture("requirements", "version_specified.txt")
+ )
+ end
+
+ its(:length) { is_expected.to eq(5) }
+
+ describe "the first dependency" do
+ subject(:dependency) { dependencies.first }
+
+ it "has the right details" do
+ expect(dependency).to be_a(Dependabot::Dependency)
+ expect(dependency.name).to eq("psycopg2")
+ expect(dependency.version).to eq("2.6.1")
+ expect(dependency.requirements).to eq(
+ [{
+ requirement: "==2.6.1",
+ file: "requirements-dev.txt",
+ groups: ["dev-dependencies"],
+ source: nil
+ }]
+ )
+ end
+ end
+ end
+
+ context "with dev-requirements.txt" do
+ let(:file) { [requirements] }
+ let(:requirements) do
+ Dependabot::DependencyFile.new(
+ name: "dev-requirements.txt",
+ content: fixture("requirements", "version_specified.txt")
+ )
+ end
+
+ its(:length) { is_expected.to eq(5) }
+
+ describe "the first dependency" do
+ subject(:dependency) { dependencies.first }
+
+ it "has the right details" do
+ expect(dependency).to be_a(Dependabot::Dependency)
+ expect(dependency.name).to eq("psycopg2")
+ expect(dependency.version).to eq("2.6.1")
+ expect(dependency.requirements).to eq(
+ [{
+ requirement: "==2.6.1",
+ file: "dev-requirements.txt",
+ groups: ["dev-dependencies"],
+ source: nil
+ }]
+ )
+ end
+ end
+ end
+
+ context "with requirements/dev.txt" do
+ let(:file) { [requirements] }
+ let(:requirements) do
+ Dependabot::DependencyFile.new(
+ name: "requirements/dev.txt",
+ content: fixture("requirements", "version_specified.txt")
+ )
+ end
+
+ its(:length) { is_expected.to eq(5) }
+
+ describe "the first dependency" do
+ subject(:dependency) { dependencies.first }
+
+ it "has the right details" do
+ expect(dependency).to be_a(Dependabot::Dependency)
+ expect(dependency.name).to eq("psycopg2")
+ expect(dependency.version).to eq("2.6.1")
+ expect(dependency.requirements).to eq(
+ [{
+ requirement: "==2.6.1",
+ file: "requirements/dev.txt",
+ groups: ["dev-dependencies"],
+ source: nil
+ }]
+ )
+ end
+ end
+ end
+
+ context "with child requirement files" do
+ let(:files) { [requirements, child_requirements] }
+ let(:requirements_fixture_name) { "cascading.txt" }
+ let(:child_requirements) do
+ Dependabot::DependencyFile.new(
+ name: "more_requirements.txt",
+ content: fixture("requirements", "version_specified.txt")
+ )
+ end
+
+ its(:length) { is_expected.to eq(6) }
+
+ it "has the right details" do
+ expect(dependencies).to contain_exactly(Dependabot::Dependency.new(
+ name: "requests",
+ version: "2.4.1",
+ requirements: [{
+ requirement: "==2.4.1",
+ file: "requirements.txt",
+ groups: ["dependencies"],
+ source: nil
+ }],
+ package_manager: "uv"
+ ), Dependabot::Dependency.new(
+ name: "attrs",
+ version: "18.0.0",
+ requirements: [{
+ requirement: "==18.0.0",
+ file: "more_requirements.txt",
+ groups: ["dependencies"],
+ source: nil
+ }],
+ package_manager: "uv"
+ ), Dependabot::Dependency.new(
+ name: "aiocache[redis]",
+ version: "0.10.0",
+ requirements: [{
+ requirement: "==0.10.0",
+ file: "more_requirements.txt",
+ groups: ["dependencies"],
+ source: nil
+ }],
+ package_manager: "uv"
+ ), Dependabot::Dependency.new(
+ name: "luigi",
+ version: "2.2.0",
+ requirements: [{
+ requirement: "==2.2.0",
+ file: "more_requirements.txt",
+ groups: ["dependencies"],
+ source: nil
+ }],
+ package_manager: "uv"
+ ), Dependabot::Dependency.new(
+ name: "psycopg2",
+ version: "2.6.1",
+ requirements: [{
+ requirement: "==2.6.1",
+ file: "more_requirements.txt",
+ groups: ["dependencies"],
+ source: nil
+ }],
+ package_manager: "uv"
+ ), Dependabot::Dependency.new(
+ name: "pytest",
+ version: "3.4.0",
+ requirements: [{
+ requirement: "==3.4.0",
+ file: "more_requirements.txt",
+ groups: ["dependencies"],
+ source: nil
+ }],
+ package_manager: "uv"
+ ))
+ end
+ end
+
+ context "with a pip-compile file" do
+ let(:files) { [manifest_file, generated_file] }
+ let(:manifest_file) do
+ Dependabot::DependencyFile.new(
+ name: "requirements/test.in",
+ content: fixture("pip_compile_files", manifest_fixture_name)
+ )
+ end
+ let(:generated_file) do
+ Dependabot::DependencyFile.new(
+ name: "requirements/test.txt",
+ content: fixture("requirements", generated_fixture_name)
+ )
+ end
+ let(:manifest_fixture_name) { "unpinned.in" }
+ let(:generated_fixture_name) { "pip_compile_unpinned.txt" }
+
+ its(:length) { is_expected.to eq(13) }
+
+ describe "top level dependencies" do
+ subject(:dependencies) { parser.parse.select(&:top_level?) }
+
+ its(:length) { is_expected.to eq(5) }
+
+ describe "the first dependency" do
+ subject(:dependency) { dependencies.first }
+
+ it "has the right details" do
+ expect(dependency).to be_a(Dependabot::Dependency)
+ expect(dependency.name).to eq("attrs")
+ expect(dependency.version).to eq("17.3.0")
+ expect(dependency.requirements).to eq(
+ [{
+ requirement: nil,
+ file: "requirements/test.in",
+ groups: ["dependencies"],
+ source: nil
+ }]
+ )
+ end
+ end
+
+ context "with filenames that can't be figured out" do
+ let(:generated_file) do
+ Dependabot::DependencyFile.new(
+ name: "requirements.txt",
+ content: fixture("requirements", generated_fixture_name)
+ )
+ end
+
+ describe "the first dependency" do
+ subject(:dependency) { dependencies.first }
+
+ it "has the right details" do
+ expect(dependency).to be_a(Dependabot::Dependency)
+ expect(dependency.name).to eq("apipkg")
+ expect(dependency.version).to eq("1.4")
+ expect(dependency.requirements).to eq(
+ [{
+ requirement: "==1.4",
+ file: "requirements.txt",
+ groups: ["dependencies"],
+ source: nil
+ }]
+ )
+ end
+ end
+
+ describe "the second dependency" do
+ subject(:dependency) { dependencies[1] }
+
+ it "has the right details" do
+ expect(dependency).to be_a(Dependabot::Dependency)
+ expect(dependency.name).to eq("attrs")
+ expect(dependency.version).to eq("17.3.0")
+ expect(dependency.requirements).to contain_exactly({
+ requirement: nil,
+ file: "requirements/test.in",
+ groups: ["dependencies"],
+ source: nil
+ }, {
+ requirement: "==17.3.0",
+ file: "requirements.txt",
+ groups: ["dependencies"],
+ source: nil
+ })
+ end
+ end
+ end
+
+ context "with a version bound" do
+ let(:manifest_fixture_name) { "bounded.in" }
+ let(:generated_fixture_name) { "pip_compile_bounded.txt" }
+
+ describe "the first dependency" do
+ subject(:dependency) { dependencies.first }
+
+ it "has the right details" do
+ expect(dependency).to be_a(Dependabot::Dependency)
+ expect(dependency.name).to eq("attrs")
+ expect(dependency.version).to eq("17.3.0")
+ expect(dependency.requirements).to eq(
+ [{
+ requirement: "<=17.4.0",
+ file: "requirements/test.in",
+ groups: ["dependencies"],
+ source: nil
+ }]
+ )
+ end
+ end
+
+ it "returns the correct ecosystem and package manager set" do
+ ecosystem = parser.ecosystem
+
+ expect(ecosystem.name).to eq("uv")
+ expect(ecosystem.package_manager.name).to eq("uv")
+ expect(ecosystem.package_manager.version.to_s).to eq("0.6.2")
+ expect(ecosystem.language.name).to eq("python")
+ end
+ end
+ end
+
+ context "with a mismatching name" do
+ let(:generated_file) do
+ Dependabot::DependencyFile.new(
+ name: "requirements/test-funky.txt",
+ content: fixture("requirements", generated_fixture_name)
+ )
+ end
+ let(:generated_fixture_name) { "pip_compile_unpinned_renamed.txt" }
+
+ describe "top level dependencies" do
+ subject(:dependencies) { parser.parse.select(&:top_level?) }
+
+ its(:length) { is_expected.to eq(5) }
+ end
+ end
+ end
+
+ context "with a pyproject.toml in poetry format and a lock file" do
+ let(:files) { [pyproject, poetry_lock] }
+ let(:pyproject) do
+ Dependabot::DependencyFile.new(
+ name: "pyproject.toml",
+ content: fixture("pyproject_files", "basic_poetry_dependencies.toml")
+ )
+ end
+ let(:poetry_lock) do
+ Dependabot::DependencyFile.new(
+ name: "poetry.lock",
+ content: fixture("poetry_locks", "poetry.lock")
+ )
+ end
+
+ its(:length) { is_expected.to eq(36) }
+
+ describe "top level dependencies" do
+ subject(:dependencies) { parser.parse.select(&:top_level?) }
+
+ its(:length) { is_expected.to eq(15) }
+
+ describe "the first dependency" do
+ subject(:dependency) { dependencies.first }
+
+ it "has the right details" do
+ expect(dependency).to be_a(Dependabot::Dependency)
+ expect(dependency.name).to eq("geopy")
+ expect(dependency.version).to eq("1.14.0")
+ expect(dependency.requirements).to eq(
+ [{
+ requirement: "^1.13",
+ file: "pyproject.toml",
+ groups: ["dependencies"],
+ source: nil
+ }]
+ )
+ end
+ end
+ end
+
+ context "when dealing with a requirements.txt" do
+ let(:files) { [pyproject, requirements] }
+ let(:pyproject) do
+ Dependabot::DependencyFile.new(
+ name: "pyproject.toml",
+ content: fixture("pyproject_files", "version_not_specified.toml")
+ )
+ end
+
+ its(:length) { is_expected.to eq(6) }
+
+ describe "the first dependency" do
+ subject(:dependency) { dependencies.first }
+
+ it "has the right details" do
+ # requests is only in version_not_specified.toml
+ expect(dependency).to be_a(Dependabot::Dependency)
+ expect(dependency.name).to eq("requests")
+ expect(dependency.version).to be_nil
+ expect(dependency.requirements).to eq(
+ [{
+ requirement: "*",
+ file: "pyproject.toml",
+ groups: ["dependencies"],
+ source: nil
+ }]
+ )
+ end
+ end
+
+ describe "the second dependency" do
+ subject(:dependency) { dependencies[1] }
+
+ it "has the right details" do
+ # pytest is in both files, it picks version to be the lowest
+ expect(dependency).to be_a(Dependabot::Dependency)
+ expect(dependency.name).to eq("pytest")
+ expect(dependency.version).to eq("3.4.0")
+ expect(dependency.requirements).to eq(
+ [{
+ requirement: "*",
+ file: "pyproject.toml",
+ groups: ["dependencies"],
+ source: nil
+ }, {
+ requirement: "==3.4.0",
+ file: "requirements.txt",
+ groups: ["dependencies"],
+ source: nil
+ }]
+ )
+ end
+ end
+
+ describe "the third dependency" do
+ subject(:dependency) { dependencies[2] }
+
+ it "has the right details" do
+ # psycopg2 only exists in version_specified.txt
+ expect(dependency).to be_a(Dependabot::Dependency)
+ expect(dependency.name).to eq("psycopg2")
+ expect(dependency.version).to eq("2.6.1")
+ expect(dependency.requirements).to eq(
+ [{
+ requirement: "==2.6.1",
+ file: "requirements.txt",
+ groups: ["dependencies"],
+ source: nil
+ }]
+ )
+ end
+ end
+
+ describe "a dependency in requirements.txt that only exists in the lockfile" do
+ subject(:dependency) { dependencies.find { |d| d.name == "attrs" } }
+
+ it "has the right details" do
+ # attrs2 exists in version_not_specified.lock and version_specified.txt
+ expect(dependency).to be_a(Dependabot::Dependency)
+ expect(dependency.name).to eq("attrs")
+ expect(dependency.version).to eq("18.0.0")
+ # it only has 1 requirement since it isn't in version_not_specified.toml
+ expect(dependency.requirements).to eq(
+ [{
+ requirement: "==18.0.0",
+ file: "requirements.txt",
+ groups: ["dependencies"],
+ source: nil
+ }]
+ )
+ end
+ end
+ end
+ end
+
+ context "with reject_external_code" do
+ let(:reject_external_code) { true }
+
+ it "raises UnexpectedExternalCode" do
+ expect { dependencies }.to raise_error(Dependabot::UnexpectedExternalCode)
+ end
+ end
+ end
+end
diff --git a/uv/spec/dependabot/uv/file_updater/compile_file_updater_spec.rb b/uv/spec/dependabot/uv/file_updater/compile_file_updater_spec.rb
new file mode 100644
index 00000000000..a6838240afa
--- /dev/null
+++ b/uv/spec/dependabot/uv/file_updater/compile_file_updater_spec.rb
@@ -0,0 +1,568 @@
+# typed: false
+# frozen_string_literal: true
+
+require "spec_helper"
+require "dependabot/dependency"
+require "dependabot/dependency_file"
+require "dependabot/uv/file_updater/compile_file_updater"
+require "dependabot/shared_helpers"
+
+RSpec.describe Dependabot::Uv::FileUpdater::CompileFileUpdater do
+ let(:updater) do
+ described_class.new(
+ dependency_files: dependency_files,
+ dependencies: [dependency],
+ credentials: credentials
+ )
+ end
+ let(:dependency_files) { [manifest_file, generated_file] }
+ let(:manifest_file) do
+ Dependabot::DependencyFile.new(
+ name: "requirements/test.in",
+ content: fixture("pip_compile_files", manifest_fixture_name)
+ )
+ end
+ let(:generated_file) do
+ Dependabot::DependencyFile.new(
+ name: "requirements/test.txt",
+ content: fixture("requirements", generated_fixture_name)
+ )
+ end
+ let(:manifest_fixture_name) { "unpinned.in" }
+ let(:generated_fixture_name) { "uv_pip_compile_unpinned.txt" }
+ let(:dependency) do
+ Dependabot::Dependency.new(
+ name: dependency_name,
+ version: dependency_version,
+ previous_version: dependency_previous_version,
+ requirements: dependency_requirements,
+ previous_requirements: dependency_previous_requirements,
+ package_manager: "uv"
+ )
+ end
+ let(:dependency_name) { "attrs" }
+ let(:dependency_version) { "18.1.0" }
+ let(:dependency_previous_version) { "17.3.0" }
+ let(:dependency_requirements) do
+ [{
+ file: "requirements/test.in",
+ requirement: nil,
+ groups: [],
+ source: nil
+ }]
+ end
+ let(:dependency_previous_requirements) do
+ [{
+ file: "requirements/test.in",
+ requirement: nil,
+ groups: [],
+ source: nil
+ }]
+ end
+ let(:credentials) do
+ [Dependabot::Credential.new({
+ "type" => "git_source",
+ "host" => "github.com",
+ "username" => "x-access-token",
+ "password" => "token"
+ })]
+ end
+ let(:tmp_path) { Dependabot::Utils::BUMP_TMP_DIR_PATH }
+
+ before { FileUtils.mkdir_p(tmp_path) }
+
+ describe "#updated_dependency_files" do
+ subject(:updated_files) { updater.updated_dependency_files }
+
+ it "updates the requirements.txt" do
+ expect(updated_files.count).to eq(1)
+ expect(updated_files.first.content).to include("attrs==18.1.0")
+ expect(updated_files.first.content)
+ .to include("pbr==4.0.2\n # via mock")
+ expect(updated_files.first.content).to include("# This file was autogenerated by uv")
+ expect(updated_files.first.content).not_to include("--hash=sha")
+ end
+
+ context "with a mismatch in filename" do
+ let(:generated_fixture_name) { "uv_pip_compile_unpinned_renamed.txt" }
+ let(:generated_file) do
+ Dependabot::DependencyFile.new(
+ name: "requirements/test-funky.txt",
+ content: fixture("requirements", generated_fixture_name)
+ )
+ end
+
+ it "updates the requirements.txt" do
+ expect(updated_files.count).to eq(1)
+ expect(updated_files.first.content).to include("attrs==18.1.0")
+ expect(updated_files.first.content)
+ .to include("pbr==4.0.2\n # via mock")
+ expect(updated_files.first.content).to include("# This file was autogenerated by uv")
+ expect(updated_files.first.content).not_to include("--hash=sha")
+ end
+ end
+
+ context "with uv header" do
+ let(:manifest_fixture_name) { "unpinned.in" }
+ let(:generated_fixture_name) { "uv_pip_compile.txt" }
+
+ it "upgrades attrs to latest" do
+ expect(updated_files.count).to eq(1)
+ expect(updated_files.first.content).to include("attrs==18.1.0")
+ expect(updated_files.first.content).to include("This file was autogenerated by uv")
+ expect(updated_files.first.content).to include("uv pip compile")
+ end
+ end
+
+ context "with a no-binary flag" do
+ let(:manifest_fixture_name) { "no_binary_uv.in" }
+ let(:generated_fixture_name) { "uv_pip_compile_no_binary.txt" }
+ let(:dependency_name) { "psycopg2" }
+ let(:dependency_version) { "2.7.6" }
+ let(:dependency_previous_version) { "2.7.4" }
+
+ it "updates the requirements.txt correctly" do
+ expect(updated_files.count).to eq(1)
+ expect(updated_files.first.content).to include("psycopg2==2.7.6")
+ expect(updated_files.first.content).to include("--no-binary psycopg2")
+ expect(updated_files.first.content)
+ .not_to include("--no-binary psycopg2==")
+ end
+ end
+
+ context "with hashes" do
+ let(:generated_fixture_name) { "uv_pip_compile_hashes.txt" }
+
+ it "updates the requirements.txt, keeping the hashes" do
+ expect(updated_files.count).to eq(1)
+ expect(updated_files.first.content).to include("attrs==18.1.0")
+ expect(updated_files.first.content).to include("4b90b09eeeb9b88c35bc64")
+ expect(updated_files.first.content).to include("# This file was autogenerated by uv")
+ end
+
+ context "when needing an augmented hashin" do
+ let(:manifest_fixture_name) { "extra_hashes.in" }
+ let(:generated_fixture_name) { "uv_pip_compile_extra_hashes.txt" }
+ let(:dependency_name) { "pyasn1-modules" }
+ let(:dependency_version) { "0.1.5" }
+ let(:dependency_previous_version) { "0.1.4" }
+
+ it "updates the requirements.txt, keeping all the hashes" do
+ expect(updated_files.count).to eq(1)
+ expect(updated_files.first.content)
+ .to include("# This file was autogenerated by uv")
+ expect(updated_files.first.content)
+ .to include("pyasn1-modules==0.1.5 \\\n --hash=sha256:01")
+ expect(updated_files.first.content)
+ .to include("--hash=sha256:b437be576bdf440fc0e930")
+ expect(updated_files.first.content)
+ .to include("pyasn1==0.3.7 \\\n --hash=sha256:16")
+ expect(updated_files.first.content)
+ .to include("--hash=sha256:bb6f5d5507621e0298794b")
+ expect(updated_files.first.content)
+ .to include("# via pyasn1-modules")
+ expect(updated_files.first.content).not_to include("WARNING")
+ end
+ end
+ end
+
+ context "with another dependency with an unmet marker" do
+ let(:manifest_fixture_name) { "unmet_marker.in" }
+ let(:generated_fixture_name) { "uv_pip_compile_unmet_marker.txt" }
+
+ it "updates the requirements.txt, keeping the unmet dep out of it" do
+ expect(updated_files.count).to eq(1)
+ expect(updated_files.first.content).to include("attrs==18.1.0")
+ expect(updated_files.first.content).not_to include("flaky")
+ end
+ end
+
+ context "with an unsafe dependency" do
+ let(:manifest_fixture_name) { "unsafe.in" }
+ let(:dependency_name) { "flake8" }
+ let(:dependency_version) { "3.6.0" }
+ let(:dependency_previous_version) { "3.5.0" }
+
+ context "when not including in the lockfile" do
+ let(:generated_fixture_name) { "uv_pip_compile_safe.txt" }
+
+ it "does not include the unsafe dependency" do
+ expect(updated_files.count).to eq(1)
+ expect(updated_files.first.content).to include("flake8==3.6.0")
+ # Distinct from pip-compile, which will not include setuptools as it is considered unsafe dependency
+ # UV's default will include it by default. Future major pip-tools version will do the same.
+ expect(updated_files.first.content).to include("setuptools")
+ expect(updated_files.first.content).to end_with("via flake8\n")
+ end
+ end
+
+ context "when including in the lockfile" do
+ let(:generated_fixture_name) { "uv_pip_compile_unsafe.txt" }
+
+ it "includes the unsafe dependency" do
+ expect(updated_files.count).to eq(1)
+ expect(updated_files.first.content).to include("flake8==3.6.0")
+ expect(updated_files.first.content).to include("setuptools")
+ end
+ end
+ end
+
+ context "with an import of the setup.py" do
+ let(:dependency_files) do
+ [manifest_file, generated_file, setup_file, pyproject]
+ end
+ let(:setup_file) do
+ Dependabot::DependencyFile.new(
+ name: "setup.py",
+ content: fixture("setup_files", setup_fixture_name)
+ )
+ end
+ let(:pyproject) do
+ Dependabot::DependencyFile.new(
+ name: "pyproject.toml",
+ content: fixture("pyproject_files", "black_configuration.toml")
+ )
+ end
+ let(:manifest_fixture_name) { "imports_setup.in" }
+ let(:generated_fixture_name) { "uv_pip_compile_imports_setup.txt" }
+ let(:setup_fixture_name) { "small.py" }
+
+ it "updates the requirements.txt", :slow do
+ expect(updated_files.count).to eq(1)
+ expect(updated_files.first.content).to include("attrs==18.1.0")
+ expect(updated_files.first.content)
+ .to include("-e file:///Users/greysteil/code/python-test")
+ expect(updated_files.first.content).not_to include("tmp/dependabot")
+ expect(updated_files.first.content)
+ .to include("pbr==4.0.2\n # via mock")
+ expect(updated_files.first.content).to include("# This file was autogenerated by uv")
+ expect(updated_files.first.content).not_to include("--hash=sha")
+ end
+
+ context "when needing sanitization", :slow do
+ let(:setup_fixture_name) { "small_needs_sanitizing.py" }
+
+ it "updates the requirements.txt" do
+ expect(updated_files.count).to eq(1)
+ expect(updated_files.first.content).to include("attrs==18.1.0")
+ end
+ end
+ end
+
+ context "with vcs url dependencies" do
+ let(:manifest_fixture_name) { "vcs_url.in" }
+ let(:generated_fixture_name) { "uv_pip_compile_vcs_url.txt" }
+
+ it "updates the requirements.txt" do
+ expect(updated_files.count).to eq(1)
+ expect(updated_files.first.content).to include("attrs==18.1.0")
+ expect(updated_files.first.content)
+ .to include("mock @ git+https://github.com/testing-cabal/mock.git@286792b2")
+ end
+ end
+
+ context "with a subdependency" do
+ let(:dependency_name) { "pbr" }
+ let(:dependency_version) { "4.2.0" }
+ let(:dependency_previous_version) { "4.0.2" }
+ let(:dependency_requirements) { [] }
+ let(:dependency_previous_requirements) { [] }
+
+ it "updates the requirements.txt" do
+ expect(updated_files.count).to eq(1)
+ expect(updated_files.first.content)
+ .to include("pbr==4.2.0\n # via mock")
+ end
+ end
+
+ context "when targeting a non-latest version" do
+ let(:dependency_version) { "17.4.0" }
+
+ it "updates the requirements.txt" do
+ expect(updated_files.count).to eq(1)
+ expect(updated_files.first.content).to include("attrs==17.4.0")
+ expect(updated_files.first.content)
+ .to include("pbr==4.0.2\n # via mock")
+ expect(updated_files.first.content).to include("# This file was autogenerated by uv")
+ expect(updated_files.first.content).not_to include("--hash=sha")
+ end
+ end
+
+ context "when the requirement.in file needs to be updated" do
+ let(:manifest_fixture_name) { "bounded.in" }
+ let(:generated_fixture_name) { "uv_pip_compile_bounded.txt" }
+
+ let(:dependency_requirements) do
+ [{
+ file: "requirements/test.in",
+ requirement: "<=18.1.0",
+ groups: [],
+ source: nil
+ }]
+ end
+ let(:dependency_previous_requirements) do
+ [{
+ file: "requirements/test.in",
+ requirement: "<=17.4.0",
+ groups: [],
+ source: nil
+ }]
+ end
+
+ it "updates the requirements.txt and the requirements.in" do
+ expect(updated_files.count).to eq(2)
+ expect(updated_files.first.content).to include("Attrs<=18.1.0")
+ expect(updated_files.last.content).to include("attrs==18.1.0")
+ expect(updated_files.last.content).not_to include("# via mock")
+ end
+
+ context "with an additional requirements.txt" do
+ let(:dependency_files) { [manifest_file, generated_file, other_txt] }
+ let(:other_txt) do
+ Dependabot::DependencyFile.new(
+ name: "requirements.txt",
+ content:
+ fixture("requirements", "uv_pip_compile_unpinned.txt")
+ )
+ end
+
+ let(:dependency_requirements) do
+ [{
+ file: "requirements/test.in",
+ requirement: "<=18.1.0",
+ groups: [],
+ source: nil
+ }, {
+ file: "requirements.txt",
+ requirement: "==18.1.0",
+ groups: [],
+ source: nil
+ }]
+ end
+ let(:dependency_previous_requirements) do
+ [{
+ file: "requirements/test.in",
+ requirement: "<=17.4.0",
+ groups: [],
+ source: nil
+ }, {
+ file: "requirements.txt",
+ requirement: "==17.3.0",
+ groups: [],
+ source: nil
+ }]
+ end
+
+ it "updates the other requirements.txt, too" do
+ expect(updated_files.count).to eq(3)
+ expect(updated_files.first.content).to include("Attrs<=18.1.0")
+ expect(updated_files[1].content).to include("attrs==18.1.0")
+ expect(updated_files.last.content).to include("attrs==18.1.0")
+ end
+ end
+
+ context "with multiple requirement.in files" do
+ let(:dependency_files) do
+ [
+ manifest_file, manifest_file2, manifest_file3, manifest_file4,
+ generated_file, generated_file2, generated_file3, generated_file4
+ ]
+ end
+
+ let(:manifest_file2) do
+ Dependabot::DependencyFile.new(
+ name: "requirements/dev.in",
+ content:
+ fixture("pip_compile_files", manifest_fixture_name)
+ )
+ end
+ let(:generated_file2) do
+ Dependabot::DependencyFile.new(
+ name: "requirements/dev.txt",
+ content: fixture("requirements", generated_fixture_name)
+ )
+ end
+
+ let(:manifest_file3) do
+ Dependabot::DependencyFile.new(
+ name: "requirements/mirror2.in",
+ content:
+ fixture("pip_compile_files", "imports_mirror.in")
+ )
+ end
+ let(:generated_file3) do
+ Dependabot::DependencyFile.new(
+ name: "requirements/mirror2.txt",
+ content: fixture("requirements", generated_fixture_name)
+ )
+ end
+
+ let(:manifest_file4) do
+ Dependabot::DependencyFile.new(
+ name: "requirements/mirror.in",
+ content:
+ fixture("pip_compile_files", "imports_dev.in")
+ )
+ end
+ let(:generated_file4) do
+ Dependabot::DependencyFile.new(
+ name: "requirements/mirror.txt",
+ content: fixture("requirements", generated_fixture_name)
+ )
+ end
+
+ let(:dependency_requirements) do
+ [{
+ file: "requirements/test.in",
+ requirement: "<=18.1.0",
+ groups: [],
+ source: nil
+ }, {
+ file: "requirements/dev.in",
+ requirement: "<=18.1.0",
+ groups: [],
+ source: nil
+ }]
+ end
+ let(:dependency_previous_requirements) do
+ [{
+ file: "requirements/test.in",
+ requirement: "<=17.4.0",
+ groups: [],
+ source: nil
+ }, {
+ file: "requirements/dev.in",
+ requirement: "<=17.4.0",
+ groups: [],
+ source: nil
+ }]
+ end
+
+ it "updates the other manifest file, too" do
+ expect(updated_files.count).to eq(6)
+ expect(updated_files[0].name).to eq("requirements/test.in")
+ expect(updated_files[1].name).to eq("requirements/dev.in")
+ expect(updated_files[2].name).to eq("requirements/test.txt")
+ expect(updated_files[3].name).to eq("requirements/dev.txt")
+ expect(updated_files[4].name).to eq("requirements/mirror2.txt")
+ expect(updated_files[5].name).to eq("requirements/mirror.txt")
+ expect(updated_files[0].content).to include("Attrs<=18.1.0")
+ expect(updated_files[1].content).to include("Attrs<=18.1.0")
+ expect(updated_files[2].content).to include("attrs==18.1.0")
+ expect(updated_files[3].content).to include("attrs==18.1.0")
+ expect(updated_files[4].content).to include("attrs==18.1.0")
+ expect(updated_files[5].content).to include("attrs==18.1.0")
+ end
+ end
+ end
+
+ context "with stripped extras" do
+ let(:manifest_fixture_name) { "strip_extras.in" }
+ let(:generated_fixture_name) { "uv_pip_compile_strip_extras.txt" }
+ let(:dependency_name) { "cachecontrol" }
+ let(:dependency_version) { "0.12.10" }
+ let(:dependency_previous_version) { "0.12.9" }
+
+ it "doesn't add an extras annotation on cachecontrol" do
+ expect(updated_files.count).to eq(1)
+ expect(updated_files.first.content).to include("cachecontrol==0.12.10")
+ expect(updated_files.first.content)
+ .not_to include("cachecontrol[filecache]==")
+ end
+ end
+
+ context "with no stripped extras" do
+ let(:manifest_fixture_name) { "strip_extras.in" }
+ let(:generated_fixture_name) { "uv_pip_compile_no_strip_extras.txt" }
+ let(:dependency_name) { "cachecontrol" }
+ let(:dependency_version) { "0.12.10" }
+ let(:dependency_previous_version) { "0.12.9" }
+
+ it "adds an extras annotation on cachecontrol" do
+ expect(updated_files.count).to eq(1)
+ expect(updated_files.first.content).to include("cachecontrol[filecache]==0.12.10")
+ end
+ end
+ end
+
+ describe "#package_hashes_for" do
+ let(:name) { "package_name" }
+ let(:version) { "1.0.0" }
+ let(:algorithm) { "sha256" }
+
+ context "when index_urls is not set" do
+ let(:updater) do
+ described_class.new(
+ dependencies: [],
+ dependency_files: [],
+ credentials: []
+ )
+ end
+
+ before do
+ allow(Dependabot::SharedHelpers).to receive(:run_helper_subprocess).and_return([{ "hash" => "123abc" }])
+ end
+
+ it "returns hash" do
+ result = updater.send(:package_hashes_for, name: name, version: version, algorithm: algorithm)
+ expect(result).to eq(["--hash=sha256:123abc"])
+ end
+ end
+
+ context "when multiple index_urls are set" do
+ let(:updater) do
+ described_class.new(
+ dependencies: [],
+ dependency_files: [],
+ credentials: [],
+ index_urls: [nil, "http://example.com"]
+ )
+ end
+
+ before do
+ allow(Dependabot::SharedHelpers).to receive(:run_helper_subprocess)
+ .and_return([{ "hash" => "123abc" }], [{ "hash" => "312cba" }])
+ end
+
+ it "returns returns two hashes" do
+ result = updater.send(:package_hashes_for, name: name, version: version, algorithm: algorithm)
+ expect(result).to eq(%w(--hash=sha256:123abc --hash=sha256:312cba))
+ end
+ end
+
+ context "when multiple index_urls are set but package does not exist in PyPI" do
+ let(:updater) do
+ described_class.new(
+ dependencies: [],
+ dependency_files: [],
+ credentials: [],
+ index_urls: [nil, "http://example.com"]
+ )
+ end
+
+ before do
+ allow(Dependabot::SharedHelpers).to receive(:run_helper_subprocess).with({
+ args: %w(package_name 1.0.0 sha256),
+ command: "pyenv exec python3 /opt/python/run.py",
+ function: "get_dependency_hash"
+ }).and_raise(
+ Dependabot::SharedHelpers::HelperSubprocessFailed.new(
+ message: "Error message", error_context: {}, error_class: "PackageNotFoundError"
+ )
+ )
+
+ allow(Dependabot::SharedHelpers).to receive(:run_helper_subprocess)
+ .with({
+ args: %w(package_name 1.0.0 sha256 http://example.com),
+ command: "pyenv exec python3 /opt/python/run.py",
+ function: "get_dependency_hash"
+ }).and_return([{ "hash" => "123abc" }])
+ end
+
+ it "returns returns two hashes" do
+ result = updater.send(:package_hashes_for, name: name, version: version, algorithm: algorithm)
+ expect(result).to eq(["--hash=sha256:123abc"])
+ end
+ end
+ end
+end
diff --git a/uv/spec/dependabot/uv/file_updater/pyproject_preparer_spec.rb b/uv/spec/dependabot/uv/file_updater/pyproject_preparer_spec.rb
new file mode 100644
index 00000000000..fe2418cacf3
--- /dev/null
+++ b/uv/spec/dependabot/uv/file_updater/pyproject_preparer_spec.rb
@@ -0,0 +1,220 @@
+# typed: false
+# frozen_string_literal: true
+
+require "spec_helper"
+require "dependabot/dependency"
+require "dependabot/dependency_file"
+require "dependabot/uv/file_updater/pyproject_preparer"
+
+RSpec.describe Dependabot::Uv::FileUpdater::PyprojectPreparer do
+ let(:preparer) do
+ described_class.new(
+ pyproject_content: pyproject_content,
+ lockfile: lockfile
+ )
+ end
+ let(:lockfile) { nil }
+ let(:pyproject_content) { fixture("pyproject_files", pyproject_fixture_name) }
+ let(:pyproject_fixture_name) { "basic_poetry_dependencies.toml" }
+
+ describe "#add_auth_env_vars" do
+ it "adds auth env vars when a token is present" do
+ preparer = described_class.new(
+ pyproject_content: fixture("pyproject_files", "private_source.toml"),
+ lockfile: nil
+ )
+ preparer.add_auth_env_vars([
+ {
+ "index-url" => "https://some.internal.registry.com/pypi/",
+ "token" => "hello:world"
+ }
+ ])
+ expect(ENV.delete("POETRY_HTTP_BASIC_CUSTOM_SOURCE_1_USERNAME")).to eq("hello")
+ expect(ENV.delete("POETRY_HTTP_BASIC_CUSTOM_SOURCE_1_PASSWORD")).to eq("world")
+ end
+
+ it "has no effect when a token is not present" do
+ preparer = described_class.new(
+ pyproject_content: fixture("pyproject_files", "private_source.toml"),
+ lockfile: nil
+ )
+ preparer.add_auth_env_vars([
+ {
+ "index-url" => "https://some.internal.registry.com/pypi/"
+ }
+ ])
+ expect(ENV.delete("POETRY_HTTP_BASIC_CUSTOM_SOURCE_1_USERNAME")).to be_nil
+ expect(ENV.delete("POETRY_HTTP_BASIC_CUSTOM_SOURCE_1_PASSWORD")).to be_nil
+ end
+
+ it "doesn't break when there are no private sources" do
+ preparer = described_class.new(
+ pyproject_content: pyproject_content,
+ lockfile: nil
+ )
+ expect { preparer.add_auth_env_vars(nil) }.not_to raise_error
+ end
+
+ it "doesn't break when there are private sources but no credentials" do
+ preparer = described_class.new(
+ pyproject_content: fixture("pyproject_files", "private_source.toml"),
+ lockfile: nil
+ )
+ expect { preparer.add_auth_env_vars(nil) }.not_to raise_error
+ end
+ end
+
+ describe "#sanitize" do
+ subject(:sanitized_content) { preparer.sanitize }
+
+ context "with a pyproject that doesn't need sanitizing" do
+ it { is_expected.to eq(pyproject_content) }
+ end
+
+ context "with a pyproject that has a {{ name }} variable" do
+ let(:pyproject_content) do
+ fixture("pyproject_files", "needs_sanitization.toml")
+ end
+
+ it "replaces the {{ name }} variable" do
+ expect(sanitized_content).to include('name = "something"')
+ end
+
+ it "replaces the # symbol" do
+ expect(sanitized_content).to include("Various {small} python projects.")
+ end
+ end
+ end
+
+ describe "#freeze_top_level_dependencies_except" do
+ subject(:freeze_top_level_dependencies_except) do
+ preparer.freeze_top_level_dependencies_except(dependencies)
+ end
+
+ let(:lockfile) do
+ Dependabot::DependencyFile.new(
+ name: "poetry.lock",
+ content: poetry_lock_body
+ )
+ end
+ let(:poetry_lock_body) do
+ fixture("poetry_locks", poetry_lock_fixture_name)
+ end
+ let(:poetry_lock_fixture_name) { "poetry.lock" }
+
+ context "with no dependencies to except" do
+ let(:dependencies) { [] }
+
+ it { is_expected.to include("geopy = \"1.14.0\"\n") }
+ it { is_expected.to include("hypothesis = \"3.57.0\"\n") }
+ it { is_expected.to include("python = \"^3.6 || ^3.7\"\n") }
+
+ context "with extras" do
+ let(:pyproject_fixture_name) { "extras.toml" }
+ let(:poetry_lock_fixture_name) { "extras.lock" }
+
+ it "preserves details of the extras" do
+ expect(freeze_top_level_dependencies_except).to include(
+ "[tool.poetry.dependencies.celery]\n" \
+ "extras = [\"redis\"]\n" \
+ "version = \"4.3.0\"\n"
+ )
+ end
+ end
+ end
+
+ context "with a dependency to except" do
+ let(:dependencies) do
+ [
+ Dependabot::Dependency.new(
+ name: "geopy",
+ version: "1.14.0",
+ package_manager: "uv",
+ requirements: []
+ )
+ ]
+ end
+
+ it { is_expected.to include("geopy = \"^1.13\"\n") }
+ end
+
+ context "with a multiple constraint dependency" do
+ let(:dependencies) { [] }
+
+ let(:poetry_lock_fixture_name) { "multiple_constraint_dependency.lock" }
+ let(:pyproject_fixture_name) { "multiple_constraint_dependency.toml" }
+
+ it { is_expected.to include("pytest = \"3.7.4\"\n") }
+
+ it "does not touch multiple constraint deps" do
+ expect(freeze_top_level_dependencies_except).not_to include("numpy = \"1.21.6\"")
+ end
+ end
+
+ context "with directory dependency" do
+ let(:dependencies) { [] }
+
+ let(:poetry_lock_fixture_name) { "dir_dependency.lock" }
+ let(:pyproject_fixture_name) { "dir_dependency.toml" }
+
+ it { is_expected.to include("pytest = \"3.7.4\"\n") }
+
+ it "does not include the version for path deps" do
+ expect(freeze_top_level_dependencies_except).not_to include(
+ "path = \"../toml\"\n" \
+ "version = \"0.10.0\"\n"
+ )
+ expect(freeze_top_level_dependencies_except).to include(
+ "path = \"../toml\"\n"
+ )
+ end
+ end
+
+ context "with file dependency" do
+ let(:dependencies) { [] }
+
+ let(:poetry_lock_fixture_name) { "file_dependency.lock" }
+ let(:pyproject_fixture_name) { "file_dependency.toml" }
+
+ it { is_expected.to include("pytest = \"3.7.4\"\n") }
+
+ it "does not include the version for path deps" do
+ expect(freeze_top_level_dependencies_except).not_to include(
+ "path = \"toml-8.2.54.tar.gz\"\n" \
+ "version = \"8.2.54\"\n"
+ )
+ expect(freeze_top_level_dependencies_except).to include(
+ "path = \"toml-8.2.54.tar.gz\"\n"
+ )
+ end
+ end
+
+ context "with url dependency" do
+ let(:dependencies) { [] }
+
+ let(:poetry_lock_fixture_name) { "url_dependency.lock" }
+ let(:pyproject_fixture_name) { "url_dependency.toml" }
+
+ it { is_expected.to include("pytest = \"6.2.4\"\n") }
+
+ it "does not include the version for url deps" do
+ expect(freeze_top_level_dependencies_except).not_to include(
+ "url = \"https://github.com/uiri/toml/archive/refs/tags/0.10.2.tar.gz\"\n" \
+ "version = \"0.10.2\"\n"
+ )
+ expect(freeze_top_level_dependencies_except).to include(
+ "url = \"https://github.com/uiri/toml/archive/refs/tags/0.10.2.tar.gz\"\n"
+ )
+ end
+ end
+
+ context "with a git dependency in a subdirectory" do
+ let(:dependencies) { [] }
+
+ let(:poetry_lock_fixture_name) { "git_dependency_in_a_subdirectory.lock" }
+ let(:pyproject_fixture_name) { "git_dependency_in_a_subdirectory.toml" }
+
+ it { is_expected.to include("subdirectory = \"python\"\n") }
+ end
+ end
+end
diff --git a/uv/spec/dependabot/uv/file_updater/requirement_file_updater_spec.rb b/uv/spec/dependabot/uv/file_updater/requirement_file_updater_spec.rb
new file mode 100644
index 00000000000..0678d03ca69
--- /dev/null
+++ b/uv/spec/dependabot/uv/file_updater/requirement_file_updater_spec.rb
@@ -0,0 +1,664 @@
+# typed: false
+# frozen_string_literal: true
+
+require "spec_helper"
+require "dependabot/dependency"
+require "dependabot/dependency_file"
+require "dependabot/uv/file_updater"
+require "dependabot/shared_helpers"
+
+RSpec.describe Dependabot::Uv::FileUpdater::RequirementFileUpdater do
+ let(:updater) do
+ described_class.new(
+ dependency_files: dependency_files,
+ dependencies: [dependency],
+ credentials: credentials
+ )
+ end
+ let(:dependency_files) { [requirements] }
+ let(:requirements) do
+ Dependabot::DependencyFile.new(
+ content: fixture("requirements", requirements_fixture_name),
+ name: "requirements.txt"
+ )
+ end
+ let(:requirements_fixture_name) { "version_specified.txt" }
+ let(:dependency) do
+ Dependabot::Dependency.new(
+ name: "psycopg2",
+ version: "2.8.1",
+ requirements: [{
+ file: "requirements.txt",
+ requirement: updated_requirement_string,
+ groups: [],
+ source: nil
+ }],
+ previous_requirements: [{
+ file: "requirements.txt",
+ requirement: previous_requirement_string,
+ groups: [],
+ source: nil
+ }],
+ package_manager: "uv"
+ )
+ end
+ let(:previous_requirement_string) { "==2.6.1" }
+ let(:updated_requirement_string) { "==2.8.1" }
+ let(:credentials) do
+ [Dependabot::Credential.new({
+ "type" => "git_source",
+ "host" => "github.com",
+ "username" => "x-access-token",
+ "password" => "token"
+ })]
+ end
+
+ describe "#updated_dependency_files" do
+ subject(:updated_files) { updater.updated_dependency_files }
+
+ it "returns DependencyFile objects" do
+ expect(updated_files).to all(be_a(Dependabot::DependencyFile))
+ end
+
+ its(:length) { is_expected.to eq(1) }
+
+ describe "the updated requirements_file" do
+ subject(:updated_requirements_file) do
+ updated_files.find { |f| f.name == "requirements.txt" }
+ end
+
+ its(:content) { is_expected.to include "psycopg2==2.8.1\n" }
+ its(:content) { is_expected.to include "luigi==2.2.0\n" }
+ # extras are preserved
+ its(:content) { is_expected.to include "aiocache[redis]==0.10.0\n" }
+
+ context "when only the minor version is specified" do
+ let(:requirements_fixture_name) { "minor_version_specified.txt" }
+ let(:previous_requirement_string) { "==2.6" }
+
+ its(:content) { is_expected.to include "psycopg2==2.8.1\n" }
+ end
+
+ context "when a local version is specified" do
+ let(:requirements_fixture_name) { "local_version.txt" }
+ let(:previous_requirement_string) { "==2.6.1+gc.1" }
+
+ its(:content) { is_expected.to include "psycopg2==2.8.1\n" }
+ end
+
+ context "when there is a comment" do
+ let(:requirements_fixture_name) { "comments.txt" }
+ let(:previous_requirement_string) { "==2.6.1" }
+
+ its(:content) { is_expected.to include "psycopg2==2.8.1 # Comment!\n" }
+ end
+
+ context "with an unknown package" do
+ let(:dependency) do
+ Dependabot::Dependency.new(
+ name: "some_unknown_package",
+ version: "24.3.3",
+ requirements: [{
+ file: "requirements.txt",
+ requirement: updated_requirement_string,
+ groups: [],
+ source: nil
+ }],
+ previous_requirements: [{
+ file: "requirements.txt",
+ requirement: previous_requirement_string,
+ groups: [],
+ source: nil
+ }],
+ package_manager: "uv"
+ )
+ end
+
+ let(:requirements_fixture_name) { "hashes_unknown_package.txt" }
+ let(:previous_requirement_string) { "==24.3.3" }
+ let(:updated_requirement_string) { "==24.4.0" }
+
+ context "when package is not in default index" do
+ it "raises an error" do
+ expect { updated_files }.to raise_error(Dependabot::DependencyFileNotResolvable)
+ end
+ end
+
+ context "when package is in default index" do
+ before do
+ allow(Dependabot::SharedHelpers).to receive(:run_helper_subprocess)
+ .and_return([{ "hash" => "1234567890abcdef" }])
+ end
+
+ its(:content) do
+ is_expected.to include "some_unknown_package==24.4.0"
+ is_expected.to include "--hash=sha256:1234567890abcdef"
+ end
+ end
+ end
+
+ context "when there is a range" do
+ context "with a space after the comma" do
+ let(:requirements_fixture_name) { "version_between_bounds.txt" }
+ let(:previous_requirement_string) { "<=3.0.0,==2.6.1" }
+ let(:updated_requirement_string) { "==2.8.1,<=3.0.0" }
+
+ its(:content) { is_expected.to include "psycopg2==2.8.1, <=3.0.0\n" }
+ end
+
+ context "with no space after the comma" do
+ let(:requirements) do
+ Dependabot::DependencyFile.new(
+ content: fixture("requirements", "version_between_bounds.txt")
+ .gsub(", ", ","),
+ name: "requirements.txt"
+ )
+ end
+ let(:previous_requirement_string) { "<=3.0.0,==2.6.1" }
+ let(:updated_requirement_string) { "==2.8.1,<=3.0.0" }
+
+ its(:content) { is_expected.to include "psycopg2==2.8.1,<=3.0.0\n" }
+ end
+ end
+
+ context "with substring names" do
+ let(:requirements_fixture_name) { "name_clash.txt" }
+ let(:dependency) do
+ Dependabot::Dependency.new(
+ name: "sqlalchemy",
+ version: "1.2.10",
+ requirements: [{
+ file: "requirements.txt",
+ requirement: "==1.2.10",
+ groups: [],
+ source: nil
+ }],
+ previous_requirements: [{
+ file: "requirements.txt",
+ requirement: "==1.2.9",
+ groups: [],
+ source: nil
+ }],
+ package_manager: "uv"
+ )
+ end
+
+ its(:content) { is_expected.to include "\nSQLAlchemy==1.2.10\n" }
+ its(:content) { is_expected.to include "Flask-SQLAlchemy==1.2.9\n" }
+ end
+
+ context "when there are hashes" do
+ let(:requirements_fixture_name) { "hashes.txt" }
+ let(:dependency) do
+ Dependabot::Dependency.new(
+ name: "pytest",
+ version: "3.3.1",
+ requirements: [{
+ file: "requirements.txt",
+ requirement: "==3.3.1",
+ groups: [],
+ source: nil
+ }],
+ previous_version: "3.2.3",
+ previous_requirements: [{
+ file: "requirements.txt",
+ requirement: "==3.2.3",
+ groups: [],
+ source: nil
+ }],
+ package_manager: "uv"
+ )
+ end
+
+ its(:content) do
+ is_expected.to eq(
+ "pytest==3.3.1 " \
+ "--hash=sha256:ae4a2d0bae1098bbe938ecd6c20a526d5d47a94dc42ad7" \
+ "331c9ad06d0efe4962 " \
+ "--hash=sha256:cf8436dc59d8695346fcd3ab296de46425ecab00d64096" \
+ "cebe79fb51ecb2eb93\n"
+ )
+ end
+
+ context "when using a sha512 algorithm" do
+ let(:requirements_fixture_name) { "hashes_512.txt" }
+
+ its(:content) do
+ is_expected.to include(
+ "pytest==3.3.1 " \
+ "--hash=sha512:f190f9a8a8f55e9dbf311429eb86e023e096d5388e1c4216" \
+ "fc8d833fbdec8fa67f67b89a174dfead663b34e5f5df124085825446297cf7" \
+ "d9500527d9e8ddb15d " \
+ "--hash=sha512:f3d73e475dbfbcd9f218268caefeab86038dde4380fcf727" \
+ "b3436847849e57309c14f6f9769e85502c6121dab354d20a1316e2e30249c0" \
+ "a2b28e87d90f71e65e\n"
+ )
+ end
+ end
+
+ context "with linebreaks" do
+ let(:requirements_fixture_name) { "hashes_multiline.txt" }
+
+ its(:content) do
+ is_expected.to eq(
+ "pytest==3.3.1 \\\n" \
+ " --hash=sha256:ae4a2d0bae1098bbe938ecd6c20a526d5d47a94dc4" \
+ "2ad7331c9ad06d0efe4962 \\\n" \
+ " --hash=sha256:cf8436dc59d8695346fcd3ab296de46425ecab00d6" \
+ "4096cebe79fb51ecb2eb93\n"
+ )
+ end
+ end
+
+ context "with linebreaks and no space after each hash" do
+ let(:requirements_fixture_name) { "hashes_multiline_no_space.txt" }
+
+ its(:content) do
+ is_expected.to eq(
+ "pytest==3.3.1 \\\n" \
+ " --hash=sha256:ae4a2d0bae1098bbe938ecd6c20a526d5d47a94dc4" \
+ "2ad7331c9ad06d0efe4962\\\n" \
+ " --hash=sha256:cf8436dc59d8695346fcd3ab296de46425ecab00d6" \
+ "4096cebe79fb51ecb2eb93\n"
+ )
+ end
+ end
+
+ context "with markers and linebreaks" do
+ let(:requirements_fixture_name) { "markers_and_hashes_multiline.txt" }
+
+ its(:content) do
+ is_expected.to eq(
+ "pytest==3.3.1 ; python_version=='2.7' \\\n" \
+ " --hash=sha256:ae4a2d0bae1098bbe938ecd6c20a526d5d47a94dc4" \
+ "2ad7331c9ad06d0efe4962 \\\n" \
+ " --hash=sha256:cf8436dc59d8695346fcd3ab296de46425ecab00d6" \
+ "4096cebe79fb51ecb2eb93\n"
+ )
+ end
+ end
+
+ context "with a single hash" do
+ let(:requirements_fixture_name) { "hashes_single.txt" }
+ let(:dependency) do
+ Dependabot::Dependency.new(
+ name: "flask-featureflags",
+ version: "0.6",
+ requirements: [{
+ file: "requirements.txt",
+ requirement: "==0.6",
+ groups: [],
+ source: nil
+ }],
+ previous_version: "0.5",
+ previous_requirements: [{
+ file: "requirements.txt",
+ requirement: "==0.5",
+ groups: [],
+ source: nil
+ }],
+ package_manager: "uv"
+ )
+ end
+
+ its(:content) do
+ is_expected.to eq(
+ "flask-featureflags==0.6 \\\n" \
+ " --hash=sha256:fc8490e4e4c1eac03e306fade8ef4be3cddff6229" \
+ "aaa3bb96466ede7d107b241\n"
+ )
+ end
+
+ context "when moving to multiple hashes" do
+ let(:requirements_fixture_name) { "hashes_single_to_multiple.txt" }
+ let(:dependency) do
+ Dependabot::Dependency.new(
+ name: "pytest",
+ version: "3.3.1",
+ requirements: [{
+ file: "requirements.txt",
+ requirement: "==3.3.1",
+ groups: [],
+ source: nil
+ }],
+ previous_version: "3.2.3",
+ previous_requirements: [{
+ file: "requirements.txt",
+ requirement: "==3.2.3",
+ groups: [],
+ source: nil
+ }],
+ package_manager: "uv"
+ )
+ end
+
+ its(:content) do
+ is_expected.to eq(
+ "pytest==3.3.1 " \
+ "--hash=sha256:ae4a2d0bae1098bbe938ecd6c20a526d5d47a94dc4" \
+ "2ad7331c9ad06d0efe4962 " \
+ "--hash=sha256:cf8436dc59d8695346fcd3ab296de46425ecab00d6" \
+ "4096cebe79fb51ecb2eb93\n"
+ )
+ end
+ end
+ end
+ end
+
+ context "when there are unused lines" do
+ let(:requirements_fixture_name) { "invalid_lines.txt" }
+ let(:previous_requirement_string) { "==2.6.1" }
+
+ its(:content) { is_expected.to include "psycopg2==2.8.1\n" }
+ its(:content) { is_expected.to include "# This is just a comment" }
+ end
+
+ context "when the dependency is in a child requirement file" do
+ let(:dependency_files) { [requirements, more_requirements] }
+ let(:requirements_fixture_name) { "cascading.txt" }
+
+ let(:dependency) do
+ Dependabot::Dependency.new(
+ name: "psycopg2",
+ version: "2.8.1",
+ requirements: [{
+ file: "more_requirements.txt",
+ requirement: "==2.8.1",
+ groups: [],
+ source: nil
+ }],
+ previous_requirements: [{
+ file: "more_requirements.txt",
+ requirement: "==2.6.1",
+ groups: [],
+ source: nil
+ }],
+ package_manager: "uv"
+ )
+ end
+
+ let(:more_requirements) do
+ Dependabot::DependencyFile.new(
+ content: fixture("requirements", "version_specified.txt"),
+ name: "more_requirements.txt"
+ )
+ end
+
+ it "updates and returns the right file" do
+ expect(updated_files.count).to eq(1)
+ expect(updated_files.first.content).to include("psycopg2==2.8.1\n")
+ end
+ end
+ end
+
+ context "with only a setup.py" do
+ subject(:updated_setup_file) do
+ updated_files.find { |f| f.name == "setup.py" }
+ end
+
+ let(:dependency_files) { [setup] }
+ let(:setup) do
+ Dependabot::DependencyFile.new(
+ content: fixture("setup_files", "setup.py"),
+ name: "setup.py"
+ )
+ end
+ let(:dependency) do
+ Dependabot::Dependency.new(
+ name: "psycopg2",
+ version: "2.8.1",
+ requirements: [{
+ file: "setup.py",
+ requirement: "==2.8.1",
+ groups: [],
+ source: nil
+ }],
+ previous_requirements: [{
+ file: "setup.py",
+ requirement: "==2.6.1",
+ groups: [],
+ source: nil
+ }],
+ package_manager: "uv"
+ )
+ end
+
+ its(:content) { is_expected.to include "'psycopg2==2.8.1',\n" }
+ its(:content) { is_expected.to include "pep8==1.7.0" }
+
+ context "with non-standard formatting" do
+ let(:dependency) do
+ Dependabot::Dependency.new(
+ name: "raven",
+ version: "5.34.0",
+ requirements: [{
+ file: "setup.py",
+ requirement: "==5.34.0",
+ groups: [],
+ source: nil
+ }],
+ previous_requirements: [{
+ file: "setup.py",
+ requirement: "==5.32.0",
+ groups: [],
+ source: nil
+ }],
+ package_manager: "uv"
+ )
+ end
+
+ its(:content) { is_expected.to include "'raven == 5.34.0',\n" }
+ end
+
+ context "with a prefix-matcher" do
+ let(:dependency) do
+ Dependabot::Dependency.new(
+ name: "requests",
+ version: nil,
+ requirements: [{
+ file: "setup.py",
+ requirement: "==2.13.*",
+ groups: [],
+ source: nil
+ }],
+ previous_requirements: [{
+ file: "setup.py",
+ requirement: "==2.12.*",
+ groups: [],
+ source: nil
+ }],
+ package_manager: "uv"
+ )
+ end
+
+ its(:content) { is_expected.to include "'requests==2.13.*',\n" }
+ end
+
+ context "with a range requirement" do
+ let(:dependency) do
+ Dependabot::Dependency.new(
+ name: "flake8",
+ version: nil,
+ requirements: [{
+ file: "setup.py",
+ requirement: ">2.5.4,<3.4.0",
+ groups: [],
+ source: nil
+ }],
+ previous_requirements: [{
+ file: "setup.py",
+ requirement: "<3.0.0,>2.5.4",
+ groups: [],
+ source: nil
+ }],
+ package_manager: "uv"
+ )
+ end
+
+ its(:content) { is_expected.to include "'flake8 > 2.5.4, < 3.4.0',\n" }
+ end
+ end
+
+ context "with only a setup.cfg" do
+ subject(:updated_setup_cfg_file) do
+ updated_files.find { |f| f.name == "setup.cfg" }
+ end
+
+ let(:dependency_files) { [setup_cfg] }
+ let(:setup_cfg) do
+ Dependabot::DependencyFile.new(
+ content: fixture("setup_files", "setup_with_requires.cfg"),
+ name: "setup.cfg"
+ )
+ end
+ let(:dependency) do
+ Dependabot::Dependency.new(
+ name: "psycopg2",
+ version: "2.8.1",
+ requirements: [{
+ file: "setup.cfg",
+ requirement: "==2.8.1",
+ groups: [],
+ source: nil
+ }],
+ previous_requirements: [{
+ file: "setup.cfg",
+ requirement: "==2.6.1",
+ groups: [],
+ source: nil
+ }],
+ package_manager: "uv"
+ )
+ end
+
+ its(:content) { is_expected.to include "psycopg2==2.8.1\n" }
+ its(:content) { is_expected.to include "pep8==1.7.0" }
+
+ context "with non-standard formatting" do
+ let(:dependency) do
+ Dependabot::Dependency.new(
+ name: "raven",
+ version: "5.34.0",
+ requirements: [{
+ file: "setup.cfg",
+ requirement: "==5.34.0",
+ groups: [],
+ source: nil
+ }],
+ previous_requirements: [{
+ file: "setup.cfg",
+ requirement: "==5.32.0",
+ groups: [],
+ source: nil
+ }],
+ package_manager: "uv"
+ )
+ end
+
+ its(:content) { is_expected.to include "raven == 5.34.0\n" }
+ end
+
+ context "with a prefix-matcher" do
+ let(:dependency) do
+ Dependabot::Dependency.new(
+ name: "requests",
+ version: nil,
+ requirements: [{
+ file: "setup.cfg",
+ requirement: "==2.13.*",
+ groups: [],
+ source: nil
+ }],
+ previous_requirements: [{
+ file: "setup.cfg",
+ requirement: "==2.12.*",
+ groups: [],
+ source: nil
+ }],
+ package_manager: "uv"
+ )
+ end
+
+ its(:content) { is_expected.to include "requests==2.13.*\n" }
+ end
+
+ context "with a range requirement" do
+ let(:dependency) do
+ Dependabot::Dependency.new(
+ name: "flake8",
+ version: nil,
+ requirements: [{
+ file: "setup.cfg",
+ requirement: ">2.5.4,<3.4.0",
+ groups: [],
+ source: nil
+ }],
+ previous_requirements: [{
+ file: "setup.cfg",
+ requirement: "<3.0.0,>2.5.4",
+ groups: [],
+ source: nil
+ }],
+ package_manager: "uv"
+ )
+ end
+
+ its(:content) { is_expected.to include "flake8 > 2.5.4, < 3.4.0\n" }
+ end
+ end
+
+ context "when the dependency is in constraints.txt and requirement.txt" do
+ let(:dependency_files) { [requirements, constraints] }
+ let(:requirements_fixture_name) { "specific_with_constraints.txt" }
+ let(:dependency) do
+ Dependabot::Dependency.new(
+ name: "requests",
+ version: "2.8.1",
+ requirements: [
+ {
+ file: "requirements.txt",
+ requirement: "==2.8.1",
+ groups: [],
+ source: nil
+ },
+ {
+ file: "constraints.txt",
+ requirement: "==2.8.1",
+ groups: [],
+ source: nil
+ }
+ ],
+ previous_requirements: [
+ {
+ file: "requirements.txt",
+ requirement: "==2.4.1",
+ groups: [],
+ source: nil
+ },
+ {
+ file: "constraints.txt",
+ requirement: "==2.0.0",
+ groups: [],
+ source: nil
+ }
+ ],
+ package_manager: "uv"
+ )
+ end
+
+ let(:constraints) do
+ Dependabot::DependencyFile.new(
+ content: fixture("constraints", "specific.txt"),
+ name: "constraints.txt"
+ )
+ end
+
+ it "updates both files" do
+ expect(updated_files.map(&:name))
+ .to match_array(%w(requirements.txt constraints.txt))
+ expect(updated_files.first.content).to include("requests==2.8.1\n")
+ expect(updated_files.last.content).to include("requests==2.8.1\n")
+ end
+ end
+ end
+end
diff --git a/uv/spec/dependabot/uv/file_updater/requirement_replacer_spec.rb b/uv/spec/dependabot/uv/file_updater/requirement_replacer_spec.rb
new file mode 100644
index 00000000000..a9dd5cf5146
--- /dev/null
+++ b/uv/spec/dependabot/uv/file_updater/requirement_replacer_spec.rb
@@ -0,0 +1,108 @@
+# typed: false
+# frozen_string_literal: true
+
+require "spec_helper"
+require "dependabot/uv/file_updater/requirement_replacer"
+
+RSpec.describe Dependabot::Uv::FileUpdater::RequirementReplacer do
+ let(:replacer) do
+ described_class.new(
+ content: requirement_content,
+ dependency_name: dependency_name,
+ old_requirement: old_requirement,
+ new_requirement: new_requirement
+ )
+ end
+
+ let(:requirement_content) { fixture("pip_compile_files", "bounded.in") }
+ let(:dependency_name) { "attrs" }
+ let(:old_requirement) { "<=17.4.0" }
+ let(:new_requirement) { ">=17.3.0" }
+
+ describe "#updated_content" do
+ subject(:updated_content) { replacer.updated_content }
+
+ it { is_expected.to include("Attrs>=17.3.0\n") }
+ it { is_expected.to include("mock\n") }
+
+ context "with an unchanged requirement" do
+ let(:new_requirement) { old_requirement }
+
+ it { is_expected.to eq(requirement_content) }
+ end
+
+ context "with multiple requirements" do
+ let(:dependency_name) { "django" }
+ let(:requirement_content) { "django>=1.11,<1.12" }
+ # Order swapped during file parsing
+ let(:old_requirement) { "<1.12,>=1.11" }
+ let(:new_requirement) { ">=1.11.5" }
+
+ it { is_expected.to eq("django>=1.11.5") }
+
+ context "with spacing" do
+ let(:requirement_content) { "django >= 1.11, < 1.12" }
+
+ it { is_expected.to eq("django >= 1.11.5") }
+ end
+ end
+
+ context "with no requirement" do
+ let(:old_requirement) { nil }
+ let(:new_requirement) { "==1.11.5" }
+
+ context "when another requirement with the same beginning" do
+ let(:dependency_name) { "pytest" }
+
+ it { is_expected.to include("pytest==1.11.5") }
+ it { is_expected.to include("pytest-xdist\n") }
+ end
+
+ context "when another requirement with the dependency as an extra" do
+ let(:requirement_content) { fixture("pip_compile_files", "extra.in") }
+ let(:dependency_name) { "flask" }
+
+ it { is_expected.to include("flask==1.11.5") }
+ it { is_expected.to include("sentry-sdk[flask]\n") }
+ end
+
+ context "when dealing with a no-binary flag" do
+ let(:requirement_content) { "requests --no-binary requests" }
+ let(:dependency_name) { "requests" }
+
+ it { is_expected.to eq("requests==1.11.5 --no-binary requests") }
+
+ context "when dealing with a previous dependency" do
+ let(:requirement_content) { "black --no-binary black\nrequests" }
+
+ it { is_expected.to eq("black --no-binary black\nrequests==1.11.5") }
+ end
+ end
+
+ context "when another requirement with the same ending" do
+ let(:requirement_content) do
+ fixture("pip_compile_files", "superstring.in")
+ end
+ let(:dependency_name) { "sqlalchemy" }
+
+ it { is_expected.to include("\nSQLAlchemy==1.11.5") }
+ it { is_expected.to include("Flask-SQLAlchemy\n") }
+ it { is_expected.to include("zope.SQLAlchemy\n") }
+ end
+
+ context "when requirement check returns unexpected exception" do
+ subject(:req_replacer) { replacer.requirement_error_handler(exception) }
+
+ let(:exception) { Exception.new(response) }
+
+ context "with a registry that results in failed certificate error" do
+ let(:response) { "CERTIFICATE_VERIFY_FAILED" }
+
+ it "raises a helpful error" do
+ expect { req_replacer }.to raise_error(Dependabot::DependencyFileNotResolvable)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/uv/spec/dependabot/uv/file_updater_spec.rb b/uv/spec/dependabot/uv/file_updater_spec.rb
new file mode 100644
index 00000000000..aeea2051ea7
--- /dev/null
+++ b/uv/spec/dependabot/uv/file_updater_spec.rb
@@ -0,0 +1,233 @@
+# typed: false
+# frozen_string_literal: true
+
+require "spec_helper"
+require "dependabot/dependency"
+require "dependabot/dependency_file"
+require "dependabot/uv/file_updater"
+require "dependabot/shared_helpers"
+require_common_spec "file_updaters/shared_examples_for_file_updaters"
+
+RSpec.describe Dependabot::Uv::FileUpdater do
+ let(:tmp_path) { Dependabot::Utils::BUMP_TMP_DIR_PATH }
+ let(:credentials) do
+ [Dependabot::Credential.new({
+ "type" => "git_source",
+ "host" => "github.com",
+ "username" => "x-access-token",
+ "password" => "token"
+ })]
+ end
+ let(:dependency) do
+ Dependabot::Dependency.new(
+ name: "psycopg2",
+ version: "2.8.1",
+ requirements: [{
+ file: "requirements.txt",
+ requirement: "==2.8.1",
+ groups: [],
+ source: nil
+ }],
+ previous_requirements: [{
+ file: "requirements.txt",
+ requirement: "==2.6.1",
+ groups: [],
+ source: nil
+ }],
+ package_manager: "uv"
+ )
+ end
+ let(:requirements_fixture_name) { "version_specified.txt" }
+ let(:requirements) do
+ Dependabot::DependencyFile.new(
+ content: fixture("requirements", requirements_fixture_name),
+ name: "requirements.txt"
+ )
+ end
+ let(:dependency_files) { [requirements] }
+ let(:updater) do
+ described_class.new(
+ dependency_files: dependency_files,
+ dependencies: [dependency],
+ credentials: credentials
+ )
+ end
+
+ before { FileUtils.mkdir_p(tmp_path) }
+
+ it_behaves_like "a dependency file updater"
+
+ describe "#updated_files_regex" do
+ subject(:updated_files_regex) { described_class.updated_files_regex }
+
+ it "is not empty" do
+ expect(updated_files_regex).not_to be_empty
+ end
+
+ context "when files match the regex patterns" do
+ it "returns true for files that should be updated" do
+ matching_files = [
+ "requirements.txt",
+ "constraints.txt",
+ "some_dependency.in",
+ "pyproject.toml",
+ "subdirectory/requirements.txt",
+ "requirements/test.in",
+ "requirements/test.txt"
+ ]
+
+ matching_files.each do |file_name|
+ expect(updated_files_regex).to(be_any { |regex| file_name.match?(regex) })
+ end
+ end
+
+ it "returns false for files that should not be updated" do
+ non_matching_files = [
+ "README.md",
+ ".github/workflow/main.yml",
+ "some_random_file.rb",
+ "package-lock.json",
+ "package.json",
+ "Gemfile",
+ "Gemfile.lock",
+ "setup.py",
+ "setup.cfg",
+ "pyproject.lock",
+ "poetry.lock",
+ "subdirectory/Pipfile",
+ "Pipfile",
+ "Pipfile.lock"
+ ]
+
+ non_matching_files.each do |file_name|
+ expect(updated_files_regex).not_to(be_any { |regex| file_name.match?(regex) })
+ end
+ end
+ end
+ end
+
+ describe "#updated_dependency_files" do
+ subject(:updated_files) { updater.updated_dependency_files }
+
+ context "with a pip-compile file" do
+ let(:dependency_files) { [manifest_file, generated_file] }
+ let(:manifest_file) do
+ Dependabot::DependencyFile.new(
+ name: "requirements/test.in",
+ content: fixture("pip_compile_files", "unpinned.in")
+ )
+ end
+ let(:generated_file) do
+ Dependabot::DependencyFile.new(
+ name: "requirements/test.txt",
+ content: fixture("requirements", "pip_compile_unpinned.txt")
+ )
+ end
+ let(:dependency) do
+ Dependabot::Dependency.new(
+ name: "psycopg2",
+ version: "2.8.1",
+ requirements: [{
+ file: "requirements/test.in",
+ requirement: "==2.8.1",
+ groups: [],
+ source: nil
+ }],
+ previous_requirements: [{
+ file: "requirements/test.in",
+ requirement: "==2.7.1",
+ groups: [],
+ source: nil
+ }],
+ package_manager: "uv"
+ )
+ end
+
+ it "delegates to CompileFileUpdater" do
+ dummy_updater =
+ instance_double(described_class::CompileFileUpdater)
+ allow(described_class::CompileFileUpdater).to receive(:new)
+ .and_return(dummy_updater)
+ allow(dummy_updater)
+ .to receive(:updated_dependency_files)
+ .and_return([OpenStruct.new(name: "updated files")])
+ expect(updater.updated_dependency_files)
+ .to eq([OpenStruct.new(name: "updated files")])
+ end
+
+ context "when a requirements.txt that specifies a subdependency" do
+ let(:dependency_files) { [manifest_file, generated_file, requirements] }
+ let(:manifest_fixture_name) { "requests.in" }
+ let(:generated_fixture_name) { "pip_compile_requests.txt" }
+ let(:requirements_fixture_name) { "urllib.txt" }
+ let(:pypi_url) { "https://pypi.org/simple/urllib/" }
+
+ let(:dependency_name) { "urllib" }
+ let(:dependency_version) { "1.22" }
+ let(:dependency_requirements) do
+ [{
+ file: "requirements.txt",
+ requirement: nil,
+ groups: [],
+ source: nil
+ }]
+ end
+
+ it "delegates to CompileFileUpdater" do
+ dummy_updater =
+ instance_double(described_class::CompileFileUpdater)
+ allow(described_class::CompileFileUpdater).to receive(:new)
+ .and_return(dummy_updater)
+ allow(dummy_updater)
+ .to receive(:updated_dependency_files)
+ .and_return([OpenStruct.new(name: "updated files")])
+ expect(updater.updated_dependency_files)
+ .to eq([OpenStruct.new(name: "updated files")])
+ end
+ end
+ end
+
+ describe "with no Pipfile or pip-compile files" do
+ let(:dependency_files) { [requirements] }
+
+ it "delegates to RequirementFileUpdater" do
+ expect(described_class::RequirementFileUpdater)
+ .to receive(:new).and_call_original
+ expect { updated_files }.not_to(change { Dir.entries(tmp_path) })
+ expect(updated_files).to all(be_a(Dependabot::DependencyFile))
+ end
+ end
+
+ describe "#pip_compile_index_urls" do
+ let(:instance) do
+ described_class.new(
+ dependencies: [],
+ dependency_files: [],
+ credentials: credentials
+ )
+ end
+
+ let(:credentials) { [instance_double(Dependabot::Credential, replaces_base?: replaces_base)] }
+ let(:replaces_base) { false }
+
+ before do
+ allow_any_instance_of(described_class).to receive(:check_required_files).and_return(true) # rubocop:disable RSpec/AnyInstance
+ allow(Dependabot::Uv::AuthedUrlBuilder).to receive(:authed_url).and_return("authed_url")
+ end
+
+ context "when credentials replace base" do
+ let(:replaces_base) { true }
+
+ it "returns authed urls for these credentials" do
+ expect(instance.send(:pip_compile_index_urls)).to eq(["authed_url"])
+ end
+ end
+
+ context "when credentials do not replace base" do
+ it "returns nil and authed urls for all credentials" do
+ expect(instance.send(:pip_compile_index_urls)).to eq([nil, "authed_url"])
+ end
+ end
+ end
+ end
+end
diff --git a/uv/spec/dependabot/uv/language_spec.rb b/uv/spec/dependabot/uv/language_spec.rb
new file mode 100644
index 00000000000..df46b54af58
--- /dev/null
+++ b/uv/spec/dependabot/uv/language_spec.rb
@@ -0,0 +1,70 @@
+# typed: false
+# frozen_string_literal: true
+
+require "dependabot/uv/language"
+require "dependabot/ecosystem"
+require_relative "../../spec_helper"
+
+RSpec.describe Dependabot::Uv::Language do
+ let(:language) do
+ described_class.new(
+ detected_version: detected_version,
+ raw_version: raw_version
+ )
+ end
+
+ let(:detected_version) { "3.11" }
+ let(:raw_version) { "3.13.1" }
+
+ describe "#deprecated?" do
+ it "returns false" do
+ expect(language.deprecated?).to be false
+ end
+
+ context "when detected version is deprecated but not unsupported" do
+ let(:detected_version) { "3.8.1" }
+
+ before do
+ allow(language).to receive(:unsupported?).and_return(false)
+ end
+
+ it "returns true" do
+ expect(language.deprecated?).to be true
+ end
+ end
+
+ context "when detected version is unsupported" do
+ it "returns false, as unsupported takes precedence" do
+ expect(language.deprecated?).to be false
+ end
+ end
+ end
+
+ describe "#unsupported?" do
+ it "returns false" do
+ expect(language.unsupported?).to be false
+ end
+
+ context "when detected version is unsupported" do
+ let(:detected_version) { "3.8" }
+
+ it "returns true" do
+ expect(language.unsupported?).to be true
+ end
+ end
+ end
+
+ describe "#raise_if_unsupported!" do
+ it "does not raise an error" do
+ expect { language.raise_if_unsupported! }.not_to raise_error
+ end
+
+ context "when detected version is unsupported" do
+ let(:detected_version) { "3.8" }
+
+ it "raises a ToolVersionNotSupported error" do
+ expect { language.raise_if_unsupported! }.to raise_error(Dependabot::ToolVersionNotSupported)
+ end
+ end
+ end
+end
diff --git a/uv/spec/dependabot/uv/metadata_finder_spec.rb b/uv/spec/dependabot/uv/metadata_finder_spec.rb
new file mode 100644
index 00000000000..0141071cc3e
--- /dev/null
+++ b/uv/spec/dependabot/uv/metadata_finder_spec.rb
@@ -0,0 +1,345 @@
+# typed: false
+# frozen_string_literal: true
+
+require "octokit"
+require "spec_helper"
+require "dependabot/dependency"
+require "dependabot/uv/metadata_finder"
+require_common_spec "metadata_finders/shared_examples_for_metadata_finders"
+
+RSpec.describe Dependabot::Uv::MetadataFinder do
+ subject(:finder) do
+ described_class.new(dependency: dependency, credentials: credentials)
+ end
+
+ let(:version) { "1.0" }
+ let(:dependency_name) { "luigi" }
+ let(:credentials) do
+ [Dependabot::Credential.new({
+ "type" => "git_source",
+ "host" => "github.com",
+ "username" => "x-access-token",
+ "password" => "token"
+ })]
+ end
+ let(:dependency) do
+ Dependabot::Dependency.new(
+ name: dependency_name,
+ version: version,
+ requirements: [{
+ file: "requirements.txt",
+ requirement: "==#{version}",
+ groups: [],
+ source: nil
+ }],
+ package_manager: "uv"
+ )
+ end
+
+ before do
+ stub_request(:get, "https://example.com/status").to_return(
+ status: 200,
+ body: "Not GHES",
+ headers: {}
+ )
+ stub_request(:get, "https://initd.org/status").to_return(status: 404)
+ stub_request(:get, "https://pypi.org/status").to_return(status: 404)
+ end
+
+ it_behaves_like "a dependency metadata finder"
+
+ describe "#source_url" do
+ subject(:source_url) { finder.source_url }
+
+ let(:pypi_url) { "https://pypi.org/pypi/#{dependency_name}/json" }
+
+ before do
+ stub_request(:get, pypi_url).to_return(status: 200, body: pypi_response)
+ end
+
+ context "when there is a github link in the pypi response" do
+ let(:pypi_response) { fixture("pypi", "pypi_response.json") }
+
+ it { is_expected.to eq("https://github.com/spotify/luigi") }
+
+ it "caches the call to pypi" do
+ 2.times { source_url }
+ expect(WebMock).to have_requested(:get, pypi_url).once
+ end
+ end
+
+ context "with a private index" do
+ let(:credentials) do
+ [Dependabot::Credential.new({
+ "type" => "git_source",
+ "host" => "github.com",
+ "username" => "x-access-token",
+ "password" => "token"
+ }), Dependabot::Credential.new({
+ "type" => "python_index",
+ "index-url" => "https://username:password@pypi.posrip.com/pypi/"
+ })]
+ end
+ let(:pypi_response) { fixture("pypi", "pypi_response.json") }
+
+ before do
+ private_url = "https://pypi.posrip.com/pypi/#{dependency_name}/json"
+ stub_request(:get, pypi_url).to_return(status: 404, body: "")
+ stub_request(:get, private_url)
+ .with(basic_auth: %w(username password))
+ .to_return(status: 200, body: pypi_response)
+ end
+
+ it { is_expected.to eq("https://github.com/spotify/luigi") }
+
+ context "with the creds passed as a token" do
+ let(:credentials) do
+ [Dependabot::Credential.new({
+ "type" => "git_source",
+ "host" => "github.com",
+ "username" => "x-access-token",
+ "password" => "token"
+ }), Dependabot::Credential.new({
+ "type" => "python_index",
+ "index-url" => "https://pypi.posrip.com/pypi/",
+ "token" => "username:password"
+ })]
+ end
+
+ it { is_expected.to eq("https://github.com/spotify/luigi") }
+ end
+
+ context "with the creds using an email address and basic auth" do
+ let(:credentials) do
+ [Dependabot::Credential.new({
+ "type" => "git_source",
+ "host" => "github.com",
+ "username" => "x-access-token",
+ "password" => "token"
+ }), Dependabot::Credential.new({
+ "type" => "python_index",
+ "index-url" => "https://user@mail.co:password@pypi.posrip.com/pypi/"
+ })]
+ end
+
+ before do
+ private_url = "https://pypi.posrip.com/pypi/#{dependency_name}/json"
+ stub_request(:get, private_url)
+ .with(basic_auth: %w(user@mail.co password))
+ .to_return(status: 200, body: pypi_response)
+ end
+
+ it { is_expected.to eq("https://github.com/spotify/luigi") }
+ end
+
+ context "when isn't used" do
+ before do
+ private_url = "https://pypi.posrip.com/pypi/#{dependency_name}/json"
+ stub_request(:get, private_url).to_return(status: 404, body: "")
+ stub_request(:get, pypi_url)
+ .to_return(status: 200, body: pypi_response)
+ end
+
+ it { is_expected.to eq("https://github.com/spotify/luigi") }
+
+ context "when it doesn't return json" do
+ before do
+ private_url = "https://pypi.posrip.com/pypi/#{dependency_name}/json"
+ stub_request(:get, private_url)
+ .to_return(status: 200, body: "")
+ end
+
+ it { is_expected.to eq("https://github.com/spotify/luigi") }
+ end
+ end
+ end
+
+ context "when the dependency came from a local repository" do
+ let(:pypi_response) { fixture("pypi", "pypi_response.json") }
+ let(:version) { "1.0+gc.1" }
+
+ it { is_expected.to be_nil }
+
+ it "doesn't call pypi" do
+ source_url
+ expect(WebMock).not_to have_requested(:get, pypi_url).once
+ end
+ end
+
+ context "when there is a bitbucket link in the pypi response" do
+ let(:pypi_response) { fixture("pypi", "pypi_response_bitbucket.json") }
+
+ it { is_expected.to eq("https://bitbucket.org/spotify/luigi") }
+
+ it "caches the call to pypi" do
+ 2.times { source_url }
+ expect(WebMock).to have_requested(:get, pypi_url).once
+ end
+ end
+
+ context "when there is a source link in the pypi description" do
+ let(:pypi_response) do
+ fixture("pypi", "pypi_response_description_source.json")
+ end
+
+ context "when dealing with a different dependency" do
+ before do
+ stub_request(:get, "https://github.com/benjaminp/six")
+ .to_return(status: 404, body: "")
+ end
+
+ it { is_expected.to be_nil }
+
+ it "caches the call to pypi" do
+ 2.times { source_url }
+ expect(WebMock).to have_requested(:get, pypi_url).once
+ end
+ end
+
+ context "when dealing with this dependency" do
+ let(:dependency_name) { "six" }
+
+ it { is_expected.to eq("https://github.com/benjaminp/six") }
+
+ it "caches the call to pypi" do
+ 2.times { source_url }
+ expect(WebMock).to have_requested(:get, pypi_url).once
+ end
+
+ context "with an unexpected name" do
+ let(:dependency_name) { "python-six" }
+
+ before do
+ stub_request(:get, "https://github.com/benjaminp/six")
+ .to_return(status: 200, body: "python-six")
+ end
+
+ it { is_expected.to eq("https://github.com/benjaminp/six") }
+ end
+ end
+ end
+
+ context "when there is not a recognised source link in the pypi response" do
+ let(:pypi_response) { fixture("pypi", "pypi_response_no_source.json") }
+
+ before do
+ stub_request(:get, "http://initd.org/psycopg/")
+ .to_return(status: 200, body: "no details")
+ end
+
+ it { is_expected.to be_nil }
+
+ it "caches the call to pypi" do
+ 2.times { source_url }
+ expect(WebMock).to have_requested(:get, pypi_url).once
+ end
+
+ it "caches the call to the homepage" do
+ 2.times { source_url }
+ expect(WebMock)
+ .to have_requested(:get, "http://initd.org/psycopg/").once
+ end
+
+ context "when the homepage does an infinite redirect" do
+ let(:redirect_url) { "http://initd.org/Psycopg/" }
+
+ before do
+ stub_request(:get, "http://initd.org/psycopg/")
+ .to_return(status: 302, headers: { "Location" => redirect_url })
+ stub_request(:get, redirect_url)
+ .to_return(
+ status: 302,
+ headers: { "Location" => "http://initd.org/psycopg/" }
+ )
+ end
+
+ it { is_expected.to be_nil }
+ end
+
+ context "when there are details on the home page" do
+ before do
+ stub_request(:get, "http://initd.org/psycopg/")
+ .to_return(
+ status: 200,
+ body: fixture("psycopg_homepage.html")
+ )
+ end
+
+ context "when dealing with this dependency" do
+ let(:dependency_name) { "psycopg2" }
+
+ it { is_expected.to eq("https://github.com/psycopg/psycopg2") }
+
+ context "with an unexpected name" do
+ let(:dependency_name) { "python-psycopg2" }
+
+ before do
+ stub_request(:get, "https://github.com/psycopg/psycopg2")
+ .to_return(status: 200, body: "python-psycopg2")
+ end
+
+ it { is_expected.to eq("https://github.com/psycopg/psycopg2") }
+ end
+ end
+
+ context "when dealing with another dependency" do
+ let(:dependency_name) { "luigi" }
+
+ before do
+ stub_request(:get, "https://github.com/psycopg/psycopg2")
+ .to_return(status: 200, body: "python-psycopg2")
+ end
+
+ it { is_expected.to be_nil }
+ end
+ end
+ end
+
+ context "when the pypi link resolves to a redirect" do
+ let(:redirect_url) { "https://pypi.org/pypi/LuiGi/json" }
+ let(:pypi_response) { fixture("pypi", "pypi_response.json") }
+
+ before do
+ stub_request(:get, pypi_url)
+ .to_return(status: 302, headers: { "Location" => redirect_url })
+ stub_request(:get, redirect_url)
+ .to_return(status: 200, body: pypi_response)
+ end
+
+ it { is_expected.to eq("https://github.com/spotify/luigi") }
+ end
+
+ context "when the dependency has extras" do
+ let(:dependency_name) { "celery[redis]" }
+ let(:version) { "4.3" }
+ let(:pypi_url) { "https://pypi.org/pypi/celery/json" }
+ let(:pypi_response) { fixture("pypi", "pypi_response_extras.json") }
+
+ it { is_expected.to eq("https://github.com/celery/celery") }
+ end
+
+ context "when the dependency source is in project_urls" do
+ let(:pypi_response) { fixture("pypi", "pypi_response_project_urls_source.json") }
+
+ it { is_expected.to eq("https://github.com/xxxxx/django-split-settings") }
+ end
+ end
+
+ describe "#homepage_url" do
+ subject(:homepage_url) { finder.homepage_url }
+
+ let(:pypi_url) { "https://pypi.org/pypi/#{dependency_name}/json" }
+
+ before do
+ stub_request(:get, pypi_url).to_return(status: 200, body: pypi_response)
+ end
+
+ context "when there is a homepage link in the pypi response" do
+ let(:pypi_response) { fixture("pypi", "pypi_response_no_source.json") }
+
+ it "returns the specified homepage" do
+ expect(homepage_url).to eq("http://initd.org/psycopg/")
+ end
+ end
+ end
+end
diff --git a/uv/spec/dependabot/uv/package_manager_spec.rb b/uv/spec/dependabot/uv/package_manager_spec.rb
new file mode 100644
index 00000000000..d3de474e1b2
--- /dev/null
+++ b/uv/spec/dependabot/uv/package_manager_spec.rb
@@ -0,0 +1,33 @@
+# typed: false
+# frozen_string_literal: true
+
+require "dependabot/uv/package_manager"
+require "dependabot/ecosystem"
+require "spec_helper"
+
+RSpec.describe Dependabot::Uv::PackageManager do
+ let(:package_manager) { described_class.new("0.6.2") }
+
+ describe "#initialize" do
+ context "when version is a String" do
+ it "sets the version correctly" do
+ expect(package_manager.version).to eq("0.6.2")
+ end
+
+ it "sets the name correctly" do
+ expect(package_manager.name).to eq("uv")
+ end
+ end
+
+ context "when pip-compile version extracted from pyenv is well formed" do
+ # If this test starts failing, you need to adjust the "detect_pipenv_version" function
+ # to return a valid version in format x.x, x.x.x etc. examples: 3.12.5, 3.12
+ version = Dependabot::SharedHelpers.run_shell_command("pyenv exec pip-compile --version")
+ .to_s.split("version ").last&.split(")")&.first
+
+ it "does not raise error" do
+ expect(version.match(/^\d+(?:\.\d+)*$/)).to be_truthy
+ end
+ end
+ end
+end
diff --git a/uv/spec/dependabot/uv/requirement_parser_spec.rb b/uv/spec/dependabot/uv/requirement_parser_spec.rb
new file mode 100644
index 00000000000..c2f81acc09d
--- /dev/null
+++ b/uv/spec/dependabot/uv/requirement_parser_spec.rb
@@ -0,0 +1,271 @@
+# typed: false
+# frozen_string_literal: true
+
+require "spec_helper"
+require "dependabot/uv/requirement_parser"
+
+RSpec.describe Dependabot::Uv::RequirementParser do
+ def parse(line)
+ requirement =
+ line.chomp.match(described_class::INSTALL_REQ_WITH_REQUIREMENT)
+ return if requirement.nil?
+
+ requirements = requirement[:requirements].to_s
+ .to_enum(:scan, described_class::REQUIREMENT)
+ .map do
+ {
+ comparison: Regexp.last_match[:comparison],
+ version: Regexp.last_match[:version]
+ }
+ end
+
+ hashes = requirement[:hashes].to_s
+ .to_enum(:scan, described_class::HASH)
+ .map do
+ {
+ algorithm: Regexp.last_match[:algorithm],
+ hash: Regexp.last_match[:hash]
+ }
+ end
+
+ {
+ name: requirement[:name],
+ requirements: requirements,
+ hashes: hashes,
+ markers: requirement[:markers]
+ }
+ end
+
+ describe ".parse" do
+ subject { parse(line) }
+
+ context "with a blank line" do
+ let(:line) { "" }
+
+ it { is_expected.to be_nil }
+ end
+
+ context "with just a line break" do
+ let(:line) { "\n" }
+
+ it { is_expected.to be_nil }
+ end
+
+ context "with a non-requirement line" do
+ let(:line) { "# This is just a comment" }
+
+ it { is_expected.to be_nil }
+ end
+
+ context "with a Jinja template" do
+ let(:line) { "{{ cookiecutter.package_name }}" }
+
+ it { is_expected.to be_nil }
+ end
+
+ context "with no specification" do
+ let(:line) { "luigi" }
+
+ it { is_expected.to be_nil }
+ end
+
+ context "with an epoch specification" do
+ let(:line) { "luigi==1!1.1.0" }
+
+ its([:requirements]) do
+ is_expected.to eq [{ comparison: "==", version: "1!1.1.0" }]
+ end
+ end
+
+ context "with a simple specification" do
+ let(:line) { "luigi == 0.1.0" }
+
+ its([:requirements]) do
+ is_expected.to eq [{ comparison: "==", version: "0.1.0" }]
+ end
+
+ context "without spaces" do
+ let(:line) { "luigi==0.1.0" }
+
+ its([:name]) { is_expected.to eq "luigi" }
+
+ its([:requirements]) do
+ is_expected.to eq [{ comparison: "==", version: "0.1.0" }]
+ end
+ end
+
+ context "with preceding v" do
+ let(:line) { "luigi==v0.1.0" }
+
+ its([:name]) { is_expected.to eq "luigi" }
+
+ its([:requirements]) do
+ is_expected.to eq [{ comparison: "==", version: "0.1.0" }]
+ end
+ end
+
+ context "with a comment" do
+ let(:line) { "luigi==0.1.0 # some comment" }
+
+ its([:name]) { is_expected.to eq "luigi" }
+
+ its([:requirements]) do
+ is_expected.to eq [{ comparison: "==", version: "0.1.0" }]
+ end
+ end
+
+ context "with an optional Jinja dependency" do
+ let(:line) do
+ "{% if cookiecutter.include_package == 'y' %} luigi==0.1.0 " \
+ "{% endif %}"
+ end
+
+ its([:name]) { is_expected.to eq "luigi" }
+
+ its([:requirements]) do
+ is_expected.to eq [{ comparison: "==", version: "0.1.0" }]
+ end
+ end
+
+ context "with markers" do
+ let(:line) do
+ 'luigi==0.1.0;python_version>="2.7" and ' \
+ '(sys_platform == "darwin" or sys_platform == "win32") '
+ end
+
+ its([:name]) { is_expected.to eq "luigi" }
+
+ its([:requirements]) do
+ is_expected.to eq [{ comparison: "==", version: "0.1.0" }]
+ end
+
+ its([:markers]) do
+ is_expected.to eq 'python_version>="2.7" and ' \
+ '(sys_platform == "darwin" or sys_platform == "win32")'
+ end
+ end
+
+ context "with a local version" do
+ let(:line) { "luigi==0.1.0+gc.1" }
+
+ its([:name]) { is_expected.to eq "luigi" }
+
+ its([:requirements]) do
+ is_expected.to eq [{ comparison: "==", version: "0.1.0+gc.1" }]
+ end
+ end
+
+ context "with a hash" do
+ let(:line) { "luigi==0.1.0 --hash=sha256:2ccb79b01769d9911" }
+
+ its([:name]) { is_expected.to eq "luigi" }
+
+ its([:requirements]) do
+ is_expected.to eq [{ comparison: "==", version: "0.1.0" }]
+ end
+
+ its([:hashes]) do
+ is_expected.to eq [{ algorithm: "sha256", hash: "2ccb79b01769d9911" }]
+ end
+ end
+
+ context "with multiple hashes" do
+ let(:line) do
+ "luigi==0.1.0 --hash=sha256:2ccb79b01 --hash=sha256:2ccb79b02"
+ end
+
+ its([:hashes]) do
+ is_expected.to contain_exactly({ algorithm: "sha256", hash: "2ccb79b01" },
+ { algorithm: "sha256", hash: "2ccb79b02" })
+ end
+
+ context "when spread over multiple lines" do
+ let(:line) do
+ "luigi==0.1.0 \\\n" \
+ " --hash=sha256:2ccb79b01 \\\n" \
+ " --hash=sha256:2ccb79b02"
+ end
+
+ its([:hashes]) do
+ is_expected.to contain_exactly({ algorithm: "sha256", hash: "2ccb79b01" },
+ { algorithm: "sha256", hash: "2ccb79b02" })
+ end
+ end
+
+ context "with marker" do
+ let(:line) do
+ "luigi==0.1.0 ; python_version=='2.7' " \
+ "--hash=sha256:2ccb79b01 --hash=sha256:2ccb79b02"
+ end
+
+ its([:requirements]) do
+ is_expected.to eq [{ comparison: "==", version: "0.1.0" }]
+ end
+
+ its([:markers]) do
+ is_expected.to eq "python_version=='2.7'"
+ end
+
+ its([:hashes]) do
+ is_expected.to contain_exactly({ algorithm: "sha256", hash: "2ccb79b01" },
+ { algorithm: "sha256", hash: "2ccb79b02" })
+ end
+ end
+
+ context "when spread over multiple lines with marker" do
+ let(:line) do
+ "luigi==0.1.0 ; python_version=='2.7' \\\n" \
+ " --hash=sha256:2ccb79b01 \\\n" \
+ " --hash=sha256:2ccb79b02"
+ end
+
+ its([:requirements]) do
+ is_expected.to eq [{ comparison: "==", version: "0.1.0" }]
+ end
+
+ its([:markers]) do
+ is_expected.to eq "python_version=='2.7'"
+ end
+
+ its([:hashes]) do
+ is_expected.to contain_exactly({ algorithm: "sha256", hash: "2ccb79b01" },
+ { algorithm: "sha256", hash: "2ccb79b02" })
+ end
+ end
+ end
+ end
+
+ context "with multiple specifications" do
+ let(:line) { "luigi == 0.1.0, <= 1" }
+
+ its([:requirements]) do
+ is_expected.to eq([
+ { comparison: "==", version: "0.1.0" },
+ { comparison: "<=", version: "1" }
+ ])
+ end
+
+ context "with a comment" do
+ let(:line) { "luigi == 0.1.0, <= 1 # some comment" }
+
+ its([:requirements]) do
+ is_expected.to eq([
+ { comparison: "==", version: "0.1.0" },
+ { comparison: "<=", version: "1" }
+ ])
+ end
+ end
+
+ context "with brackets" do
+ let(:line) { "luigi (>0.1.0,<2)" }
+
+ its([:requirements]) do
+ is_expected.to eq([
+ { comparison: ">", version: "0.1.0" },
+ { comparison: "<", version: "2" }
+ ])
+ end
+ end
+ end
+ end
+end
diff --git a/uv/spec/dependabot/uv/requirement_spec.rb b/uv/spec/dependabot/uv/requirement_spec.rb
new file mode 100644
index 00000000000..168dcf56f1d
--- /dev/null
+++ b/uv/spec/dependabot/uv/requirement_spec.rb
@@ -0,0 +1,322 @@
+# typed: false
+# frozen_string_literal: true
+
+require "spec_helper"
+require "dependabot/uv/requirement"
+require "dependabot/uv/version"
+
+RSpec.describe Dependabot::Uv::Requirement do
+ subject(:requirement) { described_class.new(requirement_string) }
+
+ let(:requirement_string) { ">=1.0.0" }
+ let(:version_class) { Dependabot::Uv::Version }
+
+ describe ".new" do
+ subject(:requirement) { described_class.new(requirement_string) }
+
+ context "with nil" do
+ let(:requirement_string) { nil }
+
+ it { is_expected.to eq(described_class.new(">= 0")) }
+ it { is_expected.to be_a(described_class) }
+ end
+
+ context "with only an *" do
+ let(:requirement_string) { "*" }
+
+ it { is_expected.to eq(described_class.new(">= 0")) }
+ end
+
+ context "with a ~=" do
+ let(:requirement_string) { "~= 1.3.0" }
+
+ its(:to_s) { is_expected.to eq(Gem::Requirement.new("~> 1.3.0").to_s) }
+ end
+
+ context "with a ==" do
+ let(:requirement_string) { "== 1.3.0" }
+
+ it { is_expected.to be_satisfied_by(Gem::Version.new("1.3.0")) }
+ it { is_expected.not_to be_satisfied_by(Gem::Version.new("1.3.1")) }
+
+ context "with a v-prefix" do
+ let(:requirement_string) { "== v1.3.0" }
+
+ it { is_expected.to be_satisfied_by(Gem::Version.new("1.3.0")) }
+ it { is_expected.not_to be_satisfied_by(Gem::Version.new("1.3.1")) }
+ end
+ end
+
+ context "with a ===" do
+ let(:requirement_string) { "=== 1.3.0" }
+
+ it "implements arbitrary equality" do
+ expect(requirement).to be_satisfied_by(version_class.new("1.3.0"))
+ expect(requirement).not_to be_satisfied_by(version_class.new("1.3"))
+ end
+ end
+
+ context "with a ~" do
+ let(:requirement_string) { "~1.2.3" }
+
+ its(:to_s) { is_expected.to eq(Gem::Requirement.new("~> 1.2.3").to_s) }
+
+ context "when dealing with two digits" do
+ let(:requirement_string) { "~1.2" }
+
+ its(:to_s) { is_expected.to eq(Gem::Requirement.new("~> 1.2.0").to_s) }
+ end
+
+ context "when dealing with one digits" do
+ let(:requirement_string) { "~1" }
+
+ its(:to_s) { is_expected.to eq(Gem::Requirement.new("~> 1.0").to_s) }
+ end
+ end
+
+ context "with a ^" do
+ let(:requirement_string) { "^1.2.3" }
+
+ it { is_expected.to eq(described_class.new(">= 1.2.3", "< 2.0.0.dev")) }
+
+ context "when dealing with two digits" do
+ let(:requirement_string) { "^1.2" }
+
+ it { is_expected.to eq(described_class.new(">= 1.2", "< 2.0.0.dev")) }
+ end
+
+ context "with a pre-1.0.0 dependency" do
+ let(:requirement_string) { "^0.2.3" }
+
+ it { is_expected.to eq(described_class.new(">= 0.2.3", "< 0.3.0.dev")) }
+ end
+ end
+
+ context "with an *" do
+ let(:requirement_string) { "== 1.3.*" }
+
+ its(:to_s) { is_expected.to eq(Gem::Requirement.new("~> 1.3.0.dev").to_s) }
+
+ context "without a prefix" do
+ let(:requirement_string) { "1.3.*" }
+
+ its(:to_s) do
+ is_expected.to eq(Gem::Requirement.new("~> 1.3.0.dev").to_s)
+ end
+ end
+
+ context "with a bad character after the wildcard" do
+ let(:requirement_string) { "== 1.3.*'" }
+
+ it "raises a helpful error" do
+ expect { requirement }
+ .to raise_error(Gem::Requirement::BadRequirementError)
+ end
+ end
+
+ context "with a >= op" do
+ let(:requirement_string) { ">= 1.3.*" }
+
+ it { is_expected.to eq(described_class.new(">= 1.3.dev")) }
+ end
+ end
+
+ context "with another operator after the first" do
+ let(:requirement_string) { ">=2.0<2.1" }
+
+ # Python ignores that second operator!
+ it { is_expected.to eq(Gem::Requirement.new(">=2.0")) }
+
+ context "when separated with a comma" do
+ let(:requirement_string) { ">=2.0,<2.1" }
+
+ it { is_expected.to eq(Gem::Requirement.new(">=2.0", "<2.1")) }
+ end
+
+ context "when separated by whitespace (supported by Poetry)" do
+ let(:requirement_string) { ">=2.0 <2.1" }
+
+ it { is_expected.to eq(Gem::Requirement.new(">=2.0", "<2.1")) }
+ end
+ end
+
+ context "with multiple operators after the first" do
+ let(:requirement_string) { ">=2.0<2.1<2.2" }
+
+ # Python ignores operators after the first!
+ it { is_expected.to eq(Gem::Requirement.new(">=2.0")) }
+
+ context "when separated with a comma" do
+ let(:requirement_string) { ">=2.0,<2.1,<2.2" }
+
+ it { is_expected.to eq(Gem::Requirement.new(">=2.0", "<2.1", "<2.2")) }
+ end
+
+ context "when separated by whitespace (supported by Poetry)" do
+ let(:requirement_string) { ">=2.0 <2.1 <2.2" }
+
+ it { is_expected.to eq(Gem::Requirement.new(">=2.0", "<2.1", "<2.2")) }
+ end
+ end
+
+ context "with an array" do
+ let(:requirement_string) { ["== 1.3.*", ">= 1.3.1"] }
+
+ its(:to_s) do
+ is_expected.to eq(Gem::Requirement.new(["~> 1.3.0.dev", ">= 1.3.1"]).to_s)
+ end
+ end
+
+ context "with a pre-release version" do
+ let(:requirement_string) { "== 1.3.alpha" }
+
+ it { is_expected.to be_satisfied_by(Gem::Version.new("1.3.a")) }
+ end
+ end
+
+ describe ".requirements_array" do
+ subject(:requirements_array) do
+ described_class.requirements_array(requirement_string)
+ end
+
+ context "with a single requirement" do
+ let(:requirement_string) { "1.2.1" }
+
+ it { is_expected.to eq([Gem::Requirement.new("1.2.1")]) }
+ end
+
+ context "with a illformed parentheses" do
+ let(:requirement_string) { "(== 1.2).1" }
+
+ it "raises a helpful error" do
+ expect { requirements_array }
+ .to raise_error(Gem::Requirement::BadRequirementError)
+ end
+ end
+
+ context "with an || requirement" do
+ let(:requirement_string) { "1.2.1 || >= 1.5.0" }
+
+ it "generates the correct array of requirements" do
+ expect(requirements_array)
+ .to contain_exactly(Gem::Requirement.new("1.2.1"), Gem::Requirement.new(">= 1.5.0"))
+ end
+
+ context "when python-specific requirements are generated" do
+ let(:requirement_string) { "^0.8.0 || ^1.2.0" }
+
+ it "generates the correct array of requirements" do
+ expect(requirements_array)
+ .to contain_exactly(described_class.new("^0.8.0"), described_class.new("^1.2.0"))
+ end
+ end
+ end
+
+ context "with parens wrapping an || requirement" do
+ let(:requirement_string) { "(1.2.1 || >= 1.5.0)" }
+
+ it "generates the correct array of requirements" do
+ expect(requirements_array)
+ .to contain_exactly(Gem::Requirement.new("1.2.1"), Gem::Requirement.new(">= 1.5.0"))
+ end
+ end
+
+ context "with parens inside an || requirement" do
+ let(:requirement_string) { "(1.2.1) || (>= 1.5.0)" }
+
+ it "generates the correct array of requirements" do
+ expect(requirements_array)
+ .to contain_exactly(Gem::Requirement.new("1.2.1"), Gem::Requirement.new(">= 1.5.0"))
+ end
+ end
+
+ context "with illformed parentheses inside an || requirement" do
+ let(:requirement_string) { "1.2.1) || >= 1.5.0" }
+
+ it "raises a helpful error" do
+ expect { requirements_array }
+ .to raise_error(Gem::Requirement::BadRequirementError)
+ end
+ end
+ end
+
+ describe "#satisfied_by?" do
+ subject(:requirement_satisfied_by) { requirement.satisfied_by?(version) }
+
+ context "with a Gem::Version" do
+ context "when dealing with the current version" do
+ let(:version) { Gem::Version.new("1.0.0") }
+
+ it { is_expected.to be(true) }
+
+ context "when the requirement includes a local version" do
+ let(:requirement_string) { ">=1.0.0+gc.1" }
+
+ it { is_expected.to be(false) }
+ end
+ end
+
+ context "when dealing with an out-of-range version" do
+ let(:version) { Gem::Version.new("0.9.0") }
+
+ it { is_expected.to be(false) }
+ end
+ end
+
+ context "with a Uv::Version" do
+ let(:version) { version_class.new(version_string) }
+
+ context "when dealing with the current version" do
+ let(:version_string) { "1.0.0" }
+
+ it { is_expected.to be(true) }
+
+ context "when including a local version" do
+ let(:version_string) { "1.0.0+gc.1" }
+
+ it { is_expected.to be(true) }
+ end
+
+ context "when the requirement includes a local version" do
+ let(:requirement_string) { ">=1.0.0+gc.1" }
+
+ it { is_expected.to be(false) }
+
+ context "when satisfied by the version" do
+ let(:version_string) { "1.0.0+gc.2" }
+
+ it { is_expected.to be(true) }
+ end
+ end
+ end
+
+ context "when dealing with an out-of-range version" do
+ let(:version_string) { "0.9.0" }
+
+ it { is_expected.to be(false) }
+ end
+
+ context "with a wildcard" do
+ let(:requirement_string) { "1.8.*" }
+
+ context "when a pre-release" do
+ let(:version_string) { "1.8-dev" }
+
+ it { is_expected.to be(true) }
+ end
+
+ context "when a full-release" do
+ let(:version_string) { "1.8.1" }
+
+ it { is_expected.to be(true) }
+
+ context "when out of range" do
+ let(:version_string) { "1.9.1" }
+
+ it { is_expected.to be(false) }
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/uv/spec/dependabot/uv/update_checker/index_finder_spec.rb b/uv/spec/dependabot/uv/update_checker/index_finder_spec.rb
new file mode 100644
index 00000000000..77924b5cf6d
--- /dev/null
+++ b/uv/spec/dependabot/uv/update_checker/index_finder_spec.rb
@@ -0,0 +1,334 @@
+# typed: false
+# frozen_string_literal: true
+
+require "spec_helper"
+require "dependabot/credential"
+require "dependabot/dependency_file"
+require "dependabot/uv/update_checker/index_finder"
+
+RSpec.describe Dependabot::Uv::UpdateChecker::IndexFinder do
+ let(:finder) do
+ described_class.new(
+ dependency_files: dependency_files,
+ credentials: credentials,
+ dependency: dependency
+ )
+ end
+ let(:pypi_url) { "https://pypi.org/simple/luigi/" }
+ let(:pypi_response) { fixture("pypi", "pypi_simple_response.html") }
+ let(:pipfile) do
+ Dependabot::DependencyFile.new(
+ name: "Pipfile",
+ content: fixture("pipfile_files", pipfile_fixture_name)
+ )
+ end
+ let(:pipfile_fixture_name) { "exact_version" }
+ let(:pyproject) do
+ Dependabot::DependencyFile.new(
+ name: "pyproject.toml",
+ content: fixture("pyproject_files", pyproject_fixture_name)
+ )
+ end
+ let(:pyproject_fixture_name) { "poetry_exact_requirement.toml" }
+ let(:requirements_file) do
+ Dependabot::DependencyFile.new(
+ name: "requirements.txt",
+ content: fixture("requirements", requirements_fixture_name)
+ )
+ end
+ let(:requirements_fixture_name) { "version_specified.txt" }
+ let(:pip_conf) do
+ Dependabot::DependencyFile.new(
+ name: "pip.conf",
+ content: fixture("pip_conf_files", pip_conf_fixture_name)
+ )
+ end
+ let(:pip_conf_fixture_name) { "custom_index" }
+ let(:credentials) do
+ [Dependabot::Credential.new({
+ "type" => "git_source",
+ "host" => "github.com",
+ "username" => "x-access-token",
+ "password" => "token"
+ })]
+ end
+ let(:dependency_files) { [requirements_file] }
+ let(:dependency) do
+ Dependabot::Dependency.new(
+ name: "requests",
+ version: "2.4.1",
+ requirements: [{
+ requirement: "==2.4.1",
+ file: "requirements.txt",
+ groups: ["dependencies"],
+ source: nil
+ }],
+ package_manager: "uv"
+ )
+ end
+
+ before do
+ stub_request(:get, pypi_url).to_return(status: 200, body: pypi_response)
+ end
+
+ describe "#index_urls" do
+ subject(:index_urls) { finder.index_urls }
+
+ context "without any additional indexes specified" do
+ it { is_expected.to eq(["https://pypi.org/simple/"]) }
+ end
+
+ context "with a custom index-url" do
+ let(:pypi_url) do
+ "https://pypi.weasyldev.com/weasyl/source/+simple/luigi/"
+ end
+
+ context "when setting in a pip.conf file" do
+ let(:pip_conf_fixture_name) { "custom_index" }
+ let(:dependency_files) { [pip_conf] }
+
+ it "gets the right index URL" do
+ expect(index_urls)
+ .to eq(["https://pypi.weasyldev.com/weasyl/source/+simple/"])
+ end
+ end
+
+ context "when setting in a requirements.txt file" do
+ let(:requirements_fixture_name) { "custom_index.txt" }
+ let(:dependency_files) { [requirements_file] }
+
+ it "gets the right index URL" do
+ expect(index_urls)
+ .to eq(["https://pypi.weasyldev.com/weasyl/source/+simple/"])
+ end
+
+ context "with quotes" do
+ let(:requirements_fixture_name) { "custom_index_quotes.txt" }
+ let(:dependency_files) { [requirements_file] }
+
+ it "gets the right index URL" do
+ expect(index_urls)
+ .to eq(["https://pypi.weasyldev.com/weasyl/source/+simple/"])
+ end
+ end
+ end
+
+ context "when setting in a Pipfile" do
+ let(:pipfile_fixture_name) { "private_source" }
+ let(:dependency_files) { [pipfile] }
+
+ it { is_expected.to eq(["https://some.internal.registry.com/pypi/"]) }
+
+ context "when unparseable" do
+ let(:pipfile_fixture_name) { "unparseable" }
+
+ it { is_expected.to eq(["https://pypi.org/simple/"]) }
+ end
+ end
+
+ context "when setting in a pyproject.toml" do
+ let(:pyproject_fixture_name) { "private_source.toml" }
+ let(:dependency_files) { [pyproject] }
+
+ it { is_expected.to eq(["https://some.internal.registry.com/pypi/"]) }
+
+ context "when unparseable" do
+ let(:pyproject_fixture_name) { "unparseable.toml" }
+
+ it { is_expected.to eq(["https://pypi.org/simple/"]) }
+ end
+ end
+
+ context "when pypi explicitly set in a pyproject.toml" do
+ let(:pyproject_fixture_name) { "pypi_explicit.toml" }
+ let(:dependency_files) { [pyproject] }
+
+ it { is_expected.to eq(["https://pypi.org/simple/"]) }
+ end
+
+ context "when pypi explicitly set in a pyproject.toml, in lowercase" do
+ let(:pyproject_fixture_name) { "pypi_explicit_lowercase.toml" }
+ let(:dependency_files) { [pyproject] }
+
+ it { is_expected.to eq(["https://pypi.org/simple/"]) }
+ end
+
+ context "when setting in credentials" do
+ let(:credentials) do
+ [Dependabot::Credential.new({
+ "type" => "python_index",
+ "index-url" => "https://pypi.weasyldev.com/weasyl/source/+simple",
+ "replaces-base" => true
+ })]
+ end
+
+ it "gets the right index URL" do
+ expect(index_urls)
+ .to eq(["https://pypi.weasyldev.com/weasyl/source/+simple/"])
+ end
+
+ context "with credentials passed as a token" do
+ let(:credentials) do
+ [Dependabot::Credential.new({
+ "type" => "python_index",
+ "index-url" => "https://pypi.weasyldev.com/weasyl/source/+simple",
+ "token" => "user:pass",
+ "replaces-base" => true
+ })]
+ end
+
+ it "gets the right index URL" do
+ expect(index_urls)
+ .to eq(
+ ["https://user:pass@pypi.weasyldev.com/weasyl/source/+simple/"]
+ )
+ end
+ end
+ end
+ end
+
+ context "with an extra-index-url" do
+ context "when setting in a pip.conf file" do
+ let(:pip_conf_fixture_name) { "extra_index" }
+ let(:dependency_files) { [pip_conf] }
+
+ it "gets the right index URLs" do
+ expect(index_urls).to contain_exactly("https://pypi.org/simple/", "https://pypi.weasyldev.com/weasyl/source/+simple/")
+ end
+
+ context "when including an environment variables" do
+ let(:pip_conf_fixture_name) { "extra_index_env_variable" }
+
+ it "raises a helpful error" do
+ error_class = Dependabot::PrivateSourceAuthenticationFailure
+ expect { index_urls }
+ .to raise_error(error_class) do |error|
+ expect(error.source)
+ .to eq("https://pypi.weasyldev.com/${SECURE_NAME}" \
+ "/source/+simple/")
+ end
+ end
+
+ context "when provided as a config variable" do
+ let(:credentials) do
+ [Dependabot::Credential.new({
+ "type" => "python_index",
+ "index-url" => "https://pypi.weasyldev.com/weasyl/" \
+ "source/+simple",
+ "replaces-base" => false
+ })]
+ end
+
+ it "gets the right index URLs" do
+ expect(index_urls).to contain_exactly("https://pypi.org/simple/", "https://pypi.weasyldev.com/weasyl/source/+simple/")
+ end
+
+ context "with a gemfury style" do
+ let(:credentials) do
+ [Dependabot::Credential.new({
+ "type" => "python_index",
+ "index-url" => "https://pypi.weasyldev.com/source/+simple"
+ })]
+ end
+ let(:url) { "https://pypi.weasyldev.com/source/+simple/luigi/" }
+
+ it "gets the right index URLs" do
+ expect(index_urls).to contain_exactly("https://pypi.org/simple/", "https://pypi.weasyldev.com/source/+simple/")
+ end
+ end
+
+ context "when the env variable is for basic auth details" do
+ let(:pip_conf_fixture_name) do
+ "extra_index_env_variable_basic_auth"
+ end
+
+ let(:credentials) do
+ [Dependabot::Credential.new({
+ "type" => "python_index",
+ "index-url" => "https://pypi.weasyldev.com/source/+simple",
+ "token" => "user:pass",
+ "replaces-base" => false
+ })]
+ end
+
+ it "gets the right index URLs" do
+ expect(index_urls).to contain_exactly("https://pypi.org/simple/", "https://user:pass@pypi.weasyldev.com/source/+simple/")
+ end
+ end
+ end
+ end
+ end
+
+ context "when setting in a requirements.txt file" do
+ let(:requirements_fixture_name) { "extra_index.txt" }
+ let(:dependency_files) { [requirements_file] }
+
+ it "gets the right index URLs" do
+ expect(index_urls).to contain_exactly("https://pypi.org/simple/", "https://pypi.weasyldev.com/weasyl/source/+simple/")
+ end
+
+ context "with quotes" do
+ let(:requirements_fixture_name) { "extra_index_quotes.txt" }
+
+ it "gets the right index URLs" do
+ expect(index_urls).to contain_exactly("https://pypi.org/simple/", "https://cakebot.mycloudrepo.io/public/repositories/py/")
+ end
+ end
+ end
+
+ context "when setting in a pyproject.toml file" do
+ let(:pyproject_fixture_name) { "extra_source.toml" }
+ let(:dependency_files) { [pyproject] }
+
+ it "gets the right index URLs" do
+ expect(index_urls).to contain_exactly("https://pypi.org/simple/", "https://some.internal.registry.com/pypi/")
+ end
+ end
+
+ context "when set in a pyproject.toml file and marked as explicit" do
+ let(:pyproject_fixture_name) { "extra_source_explicit.toml" }
+ let(:dependency_files) { [pyproject] }
+
+ it "gets the right index URLs" do
+ expect(index_urls).to contain_exactly("https://pypi.org/simple/")
+ end
+ end
+
+ context "when set in a pyproject.toml file and marked as explicit and specify with source" do
+ let(:pyproject_fixture_name) { "extra_source_explicit_and_package_specify_source.toml" }
+ let(:dependency_files) { [pyproject] }
+ let(:dependency) do
+ Dependabot::Dependency.new(
+ name: "requests",
+ version: "2.4.1",
+ requirements: [{
+ requirement: "==2.4.1",
+ file: "requirements.txt",
+ groups: ["dependencies"],
+ source: "custom"
+ }],
+ package_manager: "uv"
+ )
+ end
+
+ it "gets the right index URLs" do
+ expect(index_urls).to contain_exactly("https://some.internal.registry.com/pypi/")
+ end
+ end
+
+ context "when setting in credentials" do
+ let(:credentials) do
+ [Dependabot::Credential.new({
+ "type" => "python_index",
+ "index-url" => "https://pypi.weasyldev.com/weasyl/source/+simple",
+ "replaces-base" => false
+ })]
+ end
+
+ it "gets the right index URLs" do
+ expect(index_urls).to contain_exactly("https://pypi.org/simple/", "https://pypi.weasyldev.com/weasyl/source/+simple/")
+ end
+ end
+ end
+ end
+end
diff --git a/uv/spec/dependabot/uv/update_checker/latest_version_finder_spec.rb b/uv/spec/dependabot/uv/update_checker/latest_version_finder_spec.rb
new file mode 100644
index 00000000000..d0dd6aa116f
--- /dev/null
+++ b/uv/spec/dependabot/uv/update_checker/latest_version_finder_spec.rb
@@ -0,0 +1,762 @@
+# typed: false
+# frozen_string_literal: true
+
+require "spec_helper"
+require "dependabot/credential"
+require "dependabot/dependency"
+require "dependabot/dependency_file"
+require "dependabot/uv/update_checker/latest_version_finder"
+
+RSpec.describe Dependabot::Uv::UpdateChecker::LatestVersionFinder do
+ before do
+ stub_request(:get, pypi_url)
+ .with(headers: { "Accept" => "text/html" })
+ .to_return(status: 200, body: pypi_response)
+ end
+
+ let(:pypi_url) { "https://pypi.org/simple/luigi/" }
+ let(:pypi_response) { fixture("pypi", "pypi_simple_response.html") }
+ let(:finder) do
+ described_class.new(
+ dependency: dependency,
+ dependency_files: dependency_files,
+ credentials: credentials,
+ ignored_versions: ignored_versions,
+ raise_on_ignored: raise_on_ignored,
+ security_advisories: security_advisories
+ )
+ end
+ let(:credentials) do
+ [Dependabot::Credential.new({
+ "type" => "git_source",
+ "host" => "github.com",
+ "username" => "x-access-token",
+ "password" => "token"
+ })]
+ end
+ let(:ignored_versions) { [] }
+ let(:raise_on_ignored) { false }
+ let(:security_advisories) { [] }
+ let(:dependency_files) { [requirements_file] }
+ let(:pipfile) do
+ Dependabot::DependencyFile.new(
+ name: "Pipfile",
+ content: fixture("pipfile_files", pipfile_fixture_name)
+ )
+ end
+ let(:pipfile_fixture_name) { "exact_version" }
+ let(:pyproject) do
+ Dependabot::DependencyFile.new(
+ name: "pyproject.toml",
+ content: fixture("pyproject_files", pyproject_fixture_name)
+ )
+ end
+ let(:pyproject_fixture_name) { "poetry_exact_requirement.toml" }
+ let(:requirements_file) do
+ Dependabot::DependencyFile.new(
+ name: "requirements.txt",
+ content: fixture("requirements", requirements_fixture_name)
+ )
+ end
+ let(:requirements_fixture_name) { "version_specified.txt" }
+ let(:dependency) do
+ Dependabot::Dependency.new(
+ name: dependency_name,
+ version: dependency_version,
+ requirements: dependency_requirements,
+ package_manager: "uv"
+ )
+ end
+ let(:dependency_name) { "luigi" }
+ let(:dependency_version) { "2.0.0" }
+ let(:dependency_requirements) do
+ [{
+ file: "requirements.txt",
+ requirement: "==2.0.0",
+ groups: [],
+ source: nil
+ }]
+ end
+
+ describe "#latest_version" do
+ subject(:latest_version) { finder.latest_version }
+
+ it { is_expected.to eq(Gem::Version.new("2.6.0")) }
+
+ context "when the pypi link resolves to a redirect" do
+ let(:redirect_url) { "https://pypi.org/LuiGi/json" }
+
+ before do
+ stub_request(:get, pypi_url)
+ .to_return(status: 302, headers: { "Location" => redirect_url })
+ stub_request(:get, redirect_url)
+ .to_return(status: 200, body: pypi_response)
+ end
+
+ it { is_expected.to eq(Gem::Version.new("2.6.0")) }
+ end
+
+ context "when the pypi link fails at first" do
+ before do
+ stub_request(:get, pypi_url)
+ .to_raise(Excon::Error::Timeout).then
+ .to_return(status: 200, body: pypi_response)
+ end
+
+ it { is_expected.to eq(Gem::Version.new("2.6.0")) }
+ end
+
+ context "when the pypi link resolves to a 'Not Found' page" do
+ let(:pypi_response) { "Not Found (no releases)123 " }
+
+ it { is_expected.to be_nil }
+ end
+
+ context "when the PyPI response includes zipped files" do
+ let(:pypi_response) { fixture("pypi", "pypi_simple_response_zip.html") }
+
+ it { is_expected.to eq(Gem::Version.new("2.6.0")) }
+ end
+
+ context "when the pypi link responds with devpi-style" do
+ let(:pypi_response) { fixture("pypi", "pypi_simple_response_devpi.html") }
+ let(:dependency_version) { "0.9.0" }
+
+ it { is_expected.to eq(Gem::Version.new("0.10.2")) }
+ end
+
+ context "when the latest versions have been yanked" do
+ let(:pypi_response) do
+ fixture("pypi", "pypi_simple_response_yanked.html")
+ end
+
+ it { is_expected.to eq(Gem::Version.new("2.4.0")) }
+ end
+
+ context "when the PyPI response includes multi-line links" do
+ let(:pypi_response) do
+ fixture("pypi", "pypi_simple_response_multiline.html")
+ end
+
+ it { is_expected.to eq(Gem::Version.new("2.6.0")) }
+ end
+
+ context "when the PyPI response includes data-requires-python entries" do
+ let(:pypi_response) do
+ fixture("pypi", "pypi_simple_response_django.html")
+ end
+ let(:pypi_url) { "https://pypi.org/simple/django/" }
+ let(:dependency_name) { "django" }
+ let(:dependency_version) { "1.2.4" }
+
+ it { is_expected.to eq(Gem::Version.new("3.2.4")) }
+
+ context "when a python version specified" do
+ subject(:latest_python_version) { finder.latest_version(python_version: python_version) }
+
+ context "when the latest version is allowed" do
+ let(:python_version) { Dependabot::Uv::Version.new("3.6.3") }
+
+ it { is_expected.to eq(Gem::Version.new("3.2.4")) }
+ end
+
+ context "when the latest version is forbidden" do
+ let(:python_version) { Dependabot::Uv::Version.new("2.7.11") }
+
+ it { is_expected.to eq(Gem::Version.new("1.11.29")) }
+ end
+ end
+ end
+
+ context "when the dependency name isn't normalised" do
+ let(:dependency_name) { "Luigi_ext" }
+ let(:pypi_url) { "https://pypi.org/simple/luigi-ext/" }
+ let(:pypi_response) do
+ fixture("pypi", "pypi_simple_response_underscore.html")
+ end
+
+ it { is_expected.to eq(Gem::Version.new("2.6.0")) }
+
+ context "when containing spaces" do
+ let(:pypi_response) do
+ fixture("pypi", "pypi_simple_response_space.html")
+ end
+
+ it { is_expected.to eq(Gem::Version.new("2.6.0")) }
+ end
+ end
+
+ context "when the dependency name includes extras" do
+ let(:dependency_name) { "luigi[toml]" }
+
+ it { is_expected.to eq(Gem::Version.new("2.6.0")) }
+ end
+
+ context "when the user's current version is a pre-release" do
+ let(:dependency_version) { "2.6.0a1" }
+ let(:dependency_requirements) do
+ [{
+ file: "requirements.txt",
+ requirement: "==2.6.0a1",
+ groups: [],
+ source: nil
+ }]
+ end
+
+ it { is_expected.to eq(Gem::Version.new("2.7.0b1")) }
+
+ context "with a local version" do
+ let(:dependency_version) { "2.6.0a1+local.1" }
+
+ it { is_expected.to eq(Gem::Version.new("2.7.0b1")) }
+ end
+ end
+
+ context "when raise_on_ignored is enabled and later versions are allowed" do
+ let(:raise_on_ignored) { true }
+
+ it "doesn't raise an error" do
+ expect { latest_version }.not_to raise_error
+ end
+ end
+
+ context "when the user is on the latest version" do
+ let(:dependency_version) { "2.6.0" }
+
+ it { is_expected.to eq(Gem::Version.new("2.6.0")) }
+
+ context "when raise_on_ignored is enabled" do
+ let(:raise_on_ignored) { true }
+
+ it "doesn't raise an error" do
+ expect { latest_version }.not_to raise_error
+ end
+ end
+ end
+
+ context "when the dependency version isn't known" do
+ let(:dependency_version) { nil }
+
+ context "when raise_on_ignored is enabled" do
+ let(:raise_on_ignored) { true }
+
+ it "doesn't raise an error" do
+ expect { latest_version }.not_to raise_error
+ end
+ end
+ end
+
+ context "when the user is ignoring all later versions" do
+ let(:ignored_versions) { ["> 2.0.0"] }
+
+ it { is_expected.to eq(Gem::Version.new("2.0.0")) }
+
+ context "when raise_on_ignored is enabled" do
+ let(:raise_on_ignored) { true }
+
+ it "raises an error" do
+ expect { latest_version }.to raise_error(Dependabot::AllVersionsIgnored)
+ end
+ end
+ end
+
+ context "when the user is ignoring the latest version" do
+ let(:ignored_versions) { [">= 2.0.0.a, < 3.0"] }
+
+ it { is_expected.to eq(Gem::Version.new("1.3.0")) }
+ end
+
+ context "when the current requirement has a pre-release requirement" do
+ let(:dependency_version) { nil }
+ let(:dependency_requirements) do
+ [{
+ file: "requirements.txt",
+ requirement: ">=2.6.0a1",
+ groups: [],
+ source: nil
+ }]
+ end
+
+ it { is_expected.to eq(Gem::Version.new("2.7.0b1")) }
+ end
+
+ context "with a Pipfile with no source" do
+ let(:pipfile_fixture_name) { "no_source" }
+ let(:dependency_files) { [pipfile] }
+
+ it { is_expected.to eq(Gem::Version.new("2.6.0")) }
+ end
+
+ context "with a custom index-url" do
+ let(:pypi_url) do
+ "https://pypi.weasyldev.com/weasyl/source/+simple/luigi/"
+ end
+
+ context "when setting in a pip.conf file" do
+ let(:dependency_files) do
+ [
+ Dependabot::DependencyFile.new(
+ name: "pip.conf",
+ content: fixture("pip_conf_files", "custom_index")
+ )
+ ]
+ end
+
+ it { is_expected.to eq(Gem::Version.new("2.6.0")) }
+
+ context "with auth details that need handling carefully" do
+ let(:dependency_files) do
+ [
+ Dependabot::DependencyFile.new(
+ name: "pip.conf",
+ content: fixture("pip_conf_files", "custom_index_double_at")
+ )
+ ]
+ end
+
+ it { is_expected.to eq(Gem::Version.new("2.6.0")) }
+ end
+ end
+
+ context "when setting in a requirements.txt file" do
+ let(:requirements_fixture_name) { "custom_index.txt" }
+ let(:dependency_files) { [requirements_file] }
+
+ it { is_expected.to eq(Gem::Version.new("2.6.0")) }
+
+ context "when the url is invalid" do
+ let(:requirements_fixture_name) { "custom_index_invalid.txt" }
+
+ it "raises a helpful error" do
+ error_class = Dependabot::DependencyFileNotResolvable
+ expect { latest_version }
+ .to raise_error(error_class) do |error|
+ expect(error.message)
+ .to eq("Invalid URL: https://redacted@pypi.weasyldev.com/weasyl/source/+simple/")
+ end
+ end
+ end
+
+ context "when the url is invalid (env)" do
+ let(:requirements_fixture_name) { "custom_index_invalid_env.txt" }
+
+ it "raises a helpful error" do
+ error_class = Dependabot::DependencyFileNotResolvable
+ expect { latest_version }
+ .to raise_error(error_class) do |error|
+ expect(error.message)
+ .to eq("Invalid URL: $PIP_INDEX_URL/")
+ end
+ end
+ end
+
+ context "when the url is valid" do
+ let(:requirements_fixture_name) { "custom_index_valid.txt" }
+ let(:dependency_files) { [requirements_file] }
+
+ it { is_expected.to eq(Gem::Version.new("2.6.0")) }
+ end
+ end
+
+ context "when setting in a Pipfile" do
+ let(:pipfile_fixture_name) { "private_source" }
+ let(:dependency_files) { [pipfile] }
+ let(:pypi_url) { "https://some.internal.registry.com/pypi/luigi/" }
+
+ it { is_expected.to eq(Gem::Version.new("2.6.0")) }
+
+ context "when the file name is unparseable" do
+ let(:pipfile_fixture_name) { "unparseable" }
+ let(:pypi_url) { "https://pypi.org/simple/luigi/" }
+
+ it { is_expected.to eq(Gem::Version.new("2.6.0")) }
+ end
+
+ context "when url returns 403 status" do
+ let(:pypi_base_url) { "https://some.internal.registry.com/pypi/" }
+
+ before do
+ stub_request(:get, pypi_url)
+ .to_return(status: 403, body: pypi_response)
+ end
+
+ context "when the base URL also returns 403 status" do
+ before do
+ stub_request(:get, pypi_base_url)
+ .to_return(status: 403, body: pypi_response)
+ end
+
+ it "raises a helpful error" do
+ error_class = Dependabot::PrivateSourceAuthenticationFailure
+ expect { latest_version }
+ .to raise_error(error_class) do |error|
+ expect(error.source)
+ .to eq("https://some.internal.registry.com/pypi/")
+ end
+ end
+ end
+
+ context "when the base URL returns 200 status" do
+ before do
+ stub_request(:get, pypi_base_url)
+ .to_return(status: 400, body: pypi_response)
+ end
+
+ it { is_expected.to eq(Gem::Version.new("2.6.0")) }
+ end
+ end
+ end
+
+ context "when an index url set in a pyproject.toml" do
+ let(:pyproject_fixture_name) { "private_source.toml" }
+ let(:dependency_files) { [pyproject] }
+ let(:pypi_url) { "https://some.internal.registry.com/pypi/luigi/" }
+
+ it { is_expected.to eq(Gem::Version.new("2.6.0")) }
+ end
+
+ context "when an index url set in credentials" do
+ let(:credentials) do
+ [Dependabot::Credential.new({
+ "type" => "python_index",
+ "index-url" => "https://pypi.weasyldev.com/weasyl/source/+simple",
+ "replaces-base" => true
+ })]
+ end
+
+ it { is_expected.to eq(Gem::Version.new("2.6.0")) }
+
+ context "with credentials passed as a token" do
+ before do
+ stub_request(:get, pypi_url).to_return(status: 404, body: "")
+ stub_request(:get, pypi_url)
+ .with(basic_auth: %w(user pass))
+ .to_return(status: 200, body: pypi_response)
+ end
+
+ let(:credentials) do
+ [Dependabot::Credential.new({
+ "type" => "python_index",
+ "index-url" => "https://pypi.weasyldev.com/weasyl/source/+simple",
+ "token" => "user:pass",
+ "replaces-base" => true
+ })]
+ end
+
+ it { is_expected.to eq(Gem::Version.new("2.6.0")) }
+ end
+ end
+ end
+
+ context "with an extra-index-url" do
+ let(:extra_url) do
+ "https://pypi.weasyldev.com/weasyl/source/+simple/luigi/"
+ end
+ let(:extra_response) do
+ fixture("pypi", "pypi_simple_response_extra.html")
+ end
+
+ before do
+ stub_request(:get, extra_url)
+ .to_return(status: 200, body: extra_response)
+ end
+
+ context "when an extra index is set in a pip.conf file" do
+ let(:dependency_files) do
+ [
+ Dependabot::DependencyFile.new(
+ name: "pip.conf",
+ content: fixture("pip_conf_files", "extra_index")
+ )
+ ]
+ end
+
+ its(:to_s) { is_expected.to eq("3.0.0+weasyl.2") }
+
+ context "when config file includes environment variables" do
+ let(:dependency_files) do
+ [
+ Dependabot::DependencyFile.new(
+ name: "pip.conf",
+ content: fixture("pip_conf_files", "extra_index_env_variable")
+ )
+ ]
+ end
+
+ it "raises a helpful error" do
+ error_class = Dependabot::PrivateSourceAuthenticationFailure
+ expect { latest_version }
+ .to raise_error(error_class) do |error|
+ expect(error.source)
+ .to eq("https://pypi.weasyldev.com/${SECURE_NAME}" \
+ "/source/+simple/")
+ end
+ end
+
+ context "when environment variables are provided as a config variable" do
+ let(:credentials) do
+ [Dependabot::Credential.new({
+ "type" => "python_index",
+ "index-url" => "https://pypi.weasyldev.com/weasyl/" \
+ "source/+simple",
+ "replaces-base" => false
+ })]
+ end
+
+ its(:to_s) { is_expected.to eq("3.0.0+weasyl.2") }
+
+ context "with a gemfury style" do
+ let(:credentials) do
+ [Dependabot::Credential.new({
+ "type" => "python_index",
+ "index-url" => "https://pypi.weasyldev.com/source/+simple"
+ })]
+ end
+ let(:url) { "https://pypi.weasyldev.com/source/+simple/luigi/" }
+
+ before do
+ stub_request(:get, url)
+ .to_return(status: 200, body: extra_response)
+ end
+
+ its(:to_s) { is_expected.to eq("3.0.0+weasyl.2") }
+ end
+ end
+ end
+ end
+
+ context "when environment variables are set in a requirements.txt file" do
+ let(:dependency_files) do
+ [
+ Dependabot::DependencyFile.new(
+ name: "requirements.txt",
+ content: fixture("requirements", "extra_index.txt")
+ )
+ ]
+ end
+
+ its(:to_s) { is_expected.to eq("3.0.0+weasyl.2") }
+
+ context "when request times out" do
+ before do
+ stub_request(:get, extra_url).to_raise(Excon::Error::Timeout)
+ end
+
+ it "raises a helpful error" do
+ error_class = Dependabot::PrivateSourceTimedOut
+ expect { latest_version }
+ .to raise_error(error_class) do |error|
+ expect(error.source)
+ .to eq("https://pypi.weasyldev.com/weasyl/source/+simple/")
+ end
+ end
+ end
+ end
+
+ context "when credentials are set" do
+ let(:credentials) do
+ [Dependabot::Credential.new({
+ "type" => "python_index",
+ "index-url" => "https://pypi.weasyldev.com/weasyl/source/+simple",
+ "replaces-base" => false
+ })]
+ end
+
+ its(:to_s) { is_expected.to eq("3.0.0+weasyl.2") }
+
+ context "when the request times out" do
+ before do
+ stub_request(:get, extra_url).to_raise(Excon::Error::Timeout)
+ end
+
+ it "raises a helpful error" do
+ error_class = Dependabot::PrivateSourceTimedOut
+ expect { latest_version }
+ .to raise_error(error_class) do |error|
+ expect(error.source)
+ .to eq("https://pypi.weasyldev.com/weasyl/source/+simple/")
+ end
+ end
+ end
+ end
+ end
+ end
+
+ describe "#latest_version_with_no_unlock" do
+ subject(:latest_version_with_no_unlock) { finder.latest_version_with_no_unlock }
+
+ let(:dependency) do
+ Dependabot::Dependency.new(
+ name: dependency_name,
+ version: version,
+ requirements: requirements,
+ package_manager: "uv"
+ )
+ end
+ let(:requirements) do
+ [{ file: "req.txt", requirement: req_string, groups: [], source: nil }]
+ end
+
+ context "with no requirement" do
+ let(:req_string) { nil }
+ let(:version) { nil }
+
+ it { is_expected.to eq(Gem::Version.new("2.6.0")) }
+
+ context "when the user is ignoring the latest version" do
+ let(:ignored_versions) { [">= 2.0.0.a, < 3.0"] }
+
+ it { is_expected.to eq(Gem::Version.new("1.3.0")) }
+ end
+
+ context "when the latest versions have been yanked" do
+ let(:pypi_response) do
+ fixture("pypi", "pypi_simple_response_yanked.html")
+ end
+
+ it { is_expected.to eq(Gem::Version.new("2.4.0")) }
+ end
+
+ context "when the PyPI response includes data-requires-python entries" do
+ let(:pypi_response) do
+ fixture("pypi", "pypi_simple_response_django.html")
+ end
+ let(:pypi_url) { "https://pypi.org/simple/django/" }
+ let(:dependency_name) { "django" }
+ let(:dependency_version) { "1.2.4" }
+
+ it { is_expected.to eq(Gem::Version.new("3.2.4")) }
+
+ context "when a python version specified" do
+ subject do
+ finder.latest_version_with_no_unlock(python_version: python_version)
+ end
+
+ context "when the latest version is allowed" do
+ let(:python_version) { Dependabot::Uv::Version.new("3.6.3") }
+
+ it { is_expected.to eq(Gem::Version.new("3.2.4")) }
+ end
+
+ context "when the latest version is forbidden" do
+ let(:python_version) { Dependabot::Uv::Version.new("2.7.11") }
+
+ it { is_expected.to eq(Gem::Version.new("1.11.29")) }
+ end
+ end
+ end
+ end
+
+ context "with an equality string" do
+ let(:req_string) { "==2.0.0" }
+ let(:version) { "2.0.0" }
+
+ it { is_expected.to eq(Gem::Version.new("2.0.0")) }
+ end
+
+ context "with a >= string" do
+ let(:req_string) { ">=2.0.0" }
+ let(:version) { nil }
+
+ it { is_expected.to eq(Gem::Version.new("2.6.0")) }
+ end
+
+ context "with a full range string" do
+ let(:req_string) { ">=2.0.0,<2.5.0" }
+ let(:version) { nil }
+
+ it { is_expected.to eq(Gem::Version.new("2.4.0")) }
+ end
+
+ context "with a ~= string" do
+ let(:req_string) { "~=2.0.0" }
+ let(:version) { nil }
+
+ it { is_expected.to eq(Gem::Version.new("2.0.1")) }
+ end
+
+ context "with multiple requirements" do
+ let(:requirements) do
+ [
+ { file: "req.txt", requirement: req1, groups: [], source: nil },
+ { file: "req2.txt", requirement: req2, groups: [], source: nil }
+ ]
+ end
+ let(:req1) { "~=2.0" }
+ let(:req2) { "<=2.5.0" }
+ let(:version) { nil }
+
+ it { is_expected.to eq(Gem::Version.new("2.5.0")) }
+ end
+ end
+
+ describe "#lowest_security_fix_version" do
+ subject(:lowest_security_fix_version) { finder.lowest_security_fix_version }
+
+ let(:dependency_version) { "2.0.0" }
+ let(:security_advisories) do
+ [
+ Dependabot::SecurityAdvisory.new(
+ dependency_name: dependency_name,
+ package_manager: "uv",
+ vulnerable_versions: ["<= 2.1.0"]
+ )
+ ]
+ end
+
+ it { is_expected.to eq(Gem::Version.new("2.1.1")) }
+
+ context "when the lowest version has been yanked" do
+ let(:pypi_response) do
+ fixture("pypi", "pypi_simple_response_yanked.html")
+ end
+
+ it { is_expected.to eq(Gem::Version.new("2.2.0")) }
+ end
+
+ context "when the user has ignored all versions" do
+ let(:ignored_versions) { ["> 0"] }
+
+ it "returns nil" do
+ expect(lowest_security_fix_version).to be_nil
+ end
+
+ context "when raise_on_ignored is enabled" do
+ let(:raise_on_ignored) { true }
+
+ it "raises an error" do
+ expect { lowest_security_fix_version }.to raise_error(Dependabot::AllVersionsIgnored)
+ end
+ end
+ end
+
+ context "when the PyPI response includes data-requires-python entries" do
+ let(:pypi_response) do
+ fixture("pypi", "pypi_simple_response_django.html")
+ end
+ let(:pypi_url) { "https://pypi.org/simple/django/" }
+ let(:dependency_name) { "django" }
+ let(:dependency_version) { "1.2.4" }
+
+ it { is_expected.to eq(Gem::Version.new("2.1.1")) }
+
+ context "when a python version specified" do
+ subject do
+ finder.lowest_security_fix_version(python_version: python_version)
+ end
+
+ context "when the safe version is allowed" do
+ let(:python_version) { Dependabot::Uv::Version.new("3.6.3") }
+
+ it { is_expected.to eq(Gem::Version.new("2.1.1")) }
+ end
+
+ context "when the safe version is forbidden" do
+ let(:python_version) { Dependabot::Uv::Version.new("2.7.11") }
+
+ it { is_expected.to be_nil }
+ end
+ end
+ end
+ end
+end
diff --git a/uv/spec/dependabot/uv/update_checker/pip_version_resolver_spec.rb b/uv/spec/dependabot/uv/update_checker/pip_version_resolver_spec.rb
new file mode 100644
index 00000000000..9209a458ffd
--- /dev/null
+++ b/uv/spec/dependabot/uv/update_checker/pip_version_resolver_spec.rb
@@ -0,0 +1,150 @@
+# typed: false
+# frozen_string_literal: true
+
+require "spec_helper"
+require "dependabot/dependency"
+require "dependabot/dependency_file"
+require "dependabot/uv/update_checker/pip_version_resolver"
+
+RSpec.describe Dependabot::Uv::UpdateChecker::PipVersionResolver do
+ before do
+ stub_request(:get, pypi_url).to_return(status: 200, body: pypi_response)
+ end
+
+ let(:resolver) do
+ described_class.new(
+ dependency: dependency,
+ dependency_files: dependency_files,
+ credentials: credentials,
+ ignored_versions: ignored_versions,
+ security_advisories: security_advisories
+ )
+ end
+ let(:credentials) do
+ [Dependabot::Credential.new({
+ "type" => "git_source",
+ "host" => "github.com",
+ "username" => "x-access-token",
+ "password" => "token"
+ })]
+ end
+ let(:ignored_versions) { [] }
+ let(:security_advisories) { [] }
+ let(:dependency_files) { [requirements_file, python_version_file] }
+ let(:requirements_file) do
+ Dependabot::DependencyFile.new(
+ name: "requirements.txt",
+ content: fixture("requirements", requirements_fixture_name)
+ )
+ end
+ let(:requirements_fixture_name) { "version_specified.txt" }
+ let(:python_version_file) do
+ Dependabot::DependencyFile.new(
+ name: ".python-version",
+ content: python_version_content
+ )
+ end
+ let(:python_version_content) { "3.11.0\n" }
+ let(:pypi_response) { fixture("pypi", "pypi_simple_response_django.html") }
+ let(:pypi_url) { "https://pypi.org/simple/django/" }
+ let(:dependency) do
+ Dependabot::Dependency.new(
+ name: dependency_name,
+ version: dependency_version,
+ requirements: dependency_requirements,
+ package_manager: "uv"
+ )
+ end
+ let(:dependency_name) { "django" }
+ let(:dependency_version) { "1.2.4" }
+ let(:dependency_requirements) do
+ [{
+ file: "requirements.txt",
+ requirement: "==1.2.4",
+ groups: [],
+ source: nil
+ }]
+ end
+
+ describe "#latest_resolvable_version" do
+ subject(:latest_resolvable_version) { resolver.latest_resolvable_version }
+
+ context "with no indication of the Python version" do
+ let(:dependency_files) { [requirements_file] }
+
+ it { is_expected.to eq(Gem::Version.new("3.2.4")) }
+ end
+
+ context "with a .python-version file" do
+ let(:dependency_files) { [requirements_file, python_version_file] }
+ let(:python_version_content) { "3.11.0\n" }
+
+ it { is_expected.to eq(Gem::Version.new("3.2.4")) }
+
+ context "when the version is set to the oldest version of python supported by Dependabot" do
+ let(:python_version_content) { "3.9.0\n" }
+
+ it { is_expected.to eq(Gem::Version.new("3.2.4")) }
+ end
+
+ context "when the version is set to a python version no longer supported by Dependabot" do
+ let(:python_version_content) { "3.8.0\n" }
+
+ it "raises a helpful error" do
+ expect { latest_resolvable_version }.to raise_error(Dependabot::ToolVersionNotSupported) do |err|
+ expect(err.message).to start_with(
+ "Dependabot detected the following Python requirement for your project: '3.8.0'."
+ )
+ end
+ end
+ end
+ end
+ end
+
+ describe "#latest_resolvable_version_with_no_unlock" do
+ subject { resolver.latest_resolvable_version_with_no_unlock }
+
+ it { is_expected.to eq(Gem::Version.new("1.2.4")) }
+ end
+
+ describe "#lowest_resolvable_security_fix_version" do
+ subject(:lowest_resolvable_security_fix_version) { resolver.lowest_resolvable_security_fix_version }
+
+ let(:security_advisories) do
+ [
+ Dependabot::SecurityAdvisory.new(
+ dependency_name: dependency_name,
+ package_manager: "uv",
+ vulnerable_versions: ["<= 2.1.0"]
+ )
+ ]
+ end
+
+ it { is_expected.to eq(Gem::Version.new("2.1.1")) }
+
+ context "with a .python-version file" do
+ let(:dependency_files) { [requirements_file, python_version_file] }
+ let(:python_version_content) { "3.11.0\n" }
+
+ it { is_expected.to eq(Gem::Version.new("2.1.1")) }
+
+ context "when the version is set to the oldest version of python supported by Dependabot" do
+ let(:python_version_content) { "3.9.0\n" }
+
+ it { is_expected.to eq(Gem::Version.new("2.1.1")) }
+ end
+
+ context "when version is set to a python version no longer supported by Dependabot" do
+ let(:python_version_content) { "3.8.0\n" }
+
+ it "raises a helpful error" do
+ expect { lowest_resolvable_security_fix_version }.to raise_error(Dependabot::ToolVersionNotSupported) do |err|
+ expect(err.message).to start_with(
+ "Dependabot detected the following Python requirement for your project: '3.8.0'."
+ )
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/uv/spec/dependabot/uv/update_checker/requirements_updater_spec.rb b/uv/spec/dependabot/uv/update_checker/requirements_updater_spec.rb
new file mode 100644
index 00000000000..25e9f0f406d
--- /dev/null
+++ b/uv/spec/dependabot/uv/update_checker/requirements_updater_spec.rb
@@ -0,0 +1,776 @@
+# typed: false
+# frozen_string_literal: true
+
+require "spec_helper"
+
+require "dependabot/uv/update_checker/requirements_updater"
+require "dependabot/requirements_update_strategy"
+
+RSpec.describe Dependabot::Uv::UpdateChecker::RequirementsUpdater do
+ let(:updater) do
+ described_class.new(
+ requirements: requirements,
+ latest_resolvable_version: latest_resolvable_version,
+ update_strategy: update_strategy,
+ has_lockfile: has_lockfile
+ )
+ end
+
+ let(:update_strategy) { Dependabot::RequirementsUpdateStrategy::BumpVersions }
+ let(:requirements) { [requirement_txt_req, setup_py_req, setup_cfg_req].compact }
+ let(:requirement_txt_req) do
+ {
+ file: "requirements.txt",
+ requirement: requirement_txt_req_string,
+ groups: [],
+ source: nil
+ }
+ end
+ let(:setup_py_req) do
+ {
+ file: "setup.py",
+ requirement: setup_py_req_string,
+ groups: [],
+ source: nil
+ }
+ end
+ let(:setup_cfg_req) do
+ {
+ file: "setup.cfg",
+ requirement: setup_cfg_req_string,
+ groups: [],
+ source: nil
+ }
+ end
+ let(:requirement_txt_req_string) { "==1.4.0" }
+ let(:setup_py_req_string) { ">= 1.4.0" }
+ let(:setup_cfg_req_string) { ">= 1.4.0" }
+ let(:has_lockfile) { true }
+
+ let(:latest_resolvable_version) { "1.5.0" }
+
+ describe "#updated_requirements" do
+ subject(:updated_requirements) { updater.updated_requirements }
+
+ context "when dealing with a requirements.txt dependency" do
+ subject do
+ updated_requirements.find { |r| r[:file] == "requirements.txt" }
+ end
+
+ context "when there is no resolvable version" do
+ let(:latest_resolvable_version) { nil }
+
+ it { is_expected.to eq(requirement_txt_req) }
+ end
+
+ context "when there is a resolvable version" do
+ let(:latest_resolvable_version) { "1.5.0" }
+
+ context "when a full version was previously pinned" do
+ let(:requirement_txt_req_string) { "==1.4.0" }
+
+ its([:requirement]) { is_expected.to eq("==1.5.0") }
+
+ context "when requirement version has fewer digits than the new version" do
+ let(:requirement_txt_req_string) { "==1.4.0" }
+ let(:latest_resolvable_version) { "1.5.0.1" }
+
+ its([:requirement]) { is_expected.to eq("==1.5.0.1") }
+ end
+
+ context "when requirement has a local version" do
+ let(:requirement_txt_req_string) { "==1.4.0+gc.1" }
+
+ its([:requirement]) { is_expected.to eq("==1.5.0") }
+ end
+
+ context "when using the arbitrary equality matcher" do
+ let(:requirement_txt_req_string) { "===1.4.0" }
+
+ its([:requirement]) { is_expected.to eq("===1.5.0") }
+ end
+
+ context "when using a single equals (Poetry)" do
+ let(:requirement_txt_req_string) { "=1.4.0" }
+
+ its([:requirement]) { is_expected.to eq("=1.5.0") }
+ end
+ end
+
+ context "when no requirement is specified" do
+ let(:requirement_txt_req_string) { nil }
+
+ it { is_expected.to eq(requirement_txt_req) }
+ end
+
+ context "when an asterisk was specified" do
+ let(:requirement_txt_req_string) { "*" }
+
+ it { is_expected.to eq(requirement_txt_req) }
+ end
+
+ context "when a != req was specified" do
+ let(:requirement_txt_req_string) { "!= 1.3.0" }
+
+ it { is_expected.to eq(requirement_txt_req) }
+
+ context "when dealing with exactly the version being updated to" do
+ let(:requirement_txt_req_string) { "!=1.5.0" }
+
+ its([:requirement]) { is_expected.to eq(:unfixable) }
+ end
+ end
+
+ context "when a range requirement was specified" do
+ let(:requirement_txt_req_string) { ">=1.3.0" }
+
+ it { is_expected.to eq(requirement_txt_req) }
+
+ context "when requirement version is too high" do
+ let(:requirement_txt_req_string) { ">=2.0.0" }
+
+ its([:requirement]) { is_expected.to eq(:unfixable) }
+ end
+
+ context "when requirement had a local version" do
+ let(:requirement_txt_req_string) { ">=1.3.0+gc.1" }
+
+ it { is_expected.to eq(requirement_txt_req) }
+ end
+
+ context "with an upper bound" do
+ let(:requirement_txt_req_string) { ">=1.3.0, <=1.5.0" }
+
+ it { is_expected.to eq(requirement_txt_req) }
+
+ context "when needing an update" do
+ let(:requirement_txt_req_string) { ">=1.3.0, <1.5" }
+
+ its([:requirement]) { is_expected.to eq(">=1.3.0,<1.6") }
+
+ context "when requirement version has more digits than the new version" do
+ let(:requirement_txt_req_string) { "<=1.9.2,>=1.9" }
+ let(:latest_resolvable_version) { "1.10" }
+
+ its([:requirement]) { is_expected.to eq(">=1.9,<=1.10") }
+ end
+ end
+ end
+ end
+
+ context "when a compatibility requirement is specified" do
+ let(:requirement_txt_req_string) { "~=1.3.0" }
+
+ its([:requirement]) { is_expected.to eq("~=1.5.0") }
+
+ context "when requirement supports the new version" do
+ let(:requirement_txt_req_string) { "~=1.3" }
+
+ its([:requirement]) { is_expected.to eq("~=1.5") }
+
+ context "with the bump_versions_if_necessary update strategy" do
+ let(:update_strategy) { Dependabot::RequirementsUpdateStrategy::BumpVersionsIfNecessary }
+
+ its([:requirement]) { is_expected.to eq("~=1.3") }
+ end
+
+ context "with the widen_ranges update strategy" do
+ let(:update_strategy) { Dependabot::RequirementsUpdateStrategy::WidenRanges }
+
+ its([:requirement]) { is_expected.to eq("~=1.3") }
+ end
+ end
+
+ context "when requirement does not support the new version" do
+ let(:requirement_txt_req_string) { "~=1.3" }
+ let(:latest_resolvable_version) { "2.1.0" }
+
+ its([:requirement]) { is_expected.to eq("~=2.1") }
+
+ context "with the bump_versions_if_necessary update strategy" do
+ let(:update_strategy) { Dependabot::RequirementsUpdateStrategy::BumpVersionsIfNecessary }
+
+ its([:requirement]) { is_expected.to eq("~=2.1") }
+ end
+
+ context "with the widen_ranges update strategy" do
+ let(:update_strategy) { Dependabot::RequirementsUpdateStrategy::WidenRanges }
+
+ its([:requirement]) { is_expected.to eq(">=1.3,<3.0") }
+ end
+ end
+ end
+
+ context "when a prefix match was specified" do
+ context "when the requirement is satisfied" do
+ let(:requirement_txt_req_string) { "==1.*.*" }
+
+ it { is_expected.to eq(requirement_txt_req) }
+ end
+
+ context "when needing an update" do
+ let(:requirement_txt_req_string) { "==1.4.*" }
+
+ its([:requirement]) { is_expected.to eq("==1.5.*") }
+ end
+
+ context "when along with an exact match" do
+ let(:requirement_txt_req_string) { "==1.4.*, ==1.4.1" }
+
+ its([:requirement]) { is_expected.to eq("==1.5.0") }
+ end
+ end
+ end
+ end
+
+ context "when dealing with a setup.py dependency" do
+ subject { updated_requirements.find { |r| r[:file] == "setup.py" } }
+
+ context "when there is no resolvable version" do
+ let(:latest_resolvable_version) { nil }
+
+ it { is_expected.to eq(setup_py_req) }
+ end
+
+ context "when there is a resolvable version" do
+ let(:latest_resolvable_version) { "1.5.0" }
+
+ context "when a full version was previously pinned" do
+ let(:setup_py_req_string) { "==1.4.0" }
+
+ its([:requirement]) { is_expected.to eq("==1.5.0") }
+
+ context "when the requirement version has fewer digits than the new version" do
+ let(:setup_py_req_string) { "==1.4.0" }
+ let(:latest_resolvable_version) { "1.5.0.1" }
+
+ its([:requirement]) { is_expected.to eq("==1.5.0.1") }
+ end
+
+ context "without leading == (technically invalid)" do
+ let(:setup_py_req_string) { "1.4.0" }
+
+ its([:requirement]) { is_expected.to eq("1.5.0") }
+ end
+ end
+
+ context "when no requirement is specified" do
+ let(:setup_py_req_string) { nil }
+
+ it { is_expected.to eq(setup_py_req) }
+ end
+
+ context "when a range requirement is specified" do
+ let(:setup_py_req_string) { ">=1.3.0" }
+
+ it { is_expected.to eq(setup_py_req) }
+
+ context "when the requirement version is too high" do
+ let(:setup_py_req_string) { ">=2.0.0" }
+
+ its([:requirement]) { is_expected.to eq(:unfixable) }
+ end
+
+ context "with an upper bound" do
+ let(:setup_py_req_string) { ">=1.3.0, <=1.5.0" }
+
+ it { is_expected.to eq(setup_py_req) }
+
+ context "when needing an update" do
+ let(:setup_py_req_string) { ">=1.3.0, <1.5" }
+
+ its([:requirement]) { is_expected.to eq(">=1.3.0,<1.6") }
+ end
+ end
+ end
+
+ context "when a compatibility requirement was specified" do
+ let(:setup_py_req_string) { "~=1.3.0" }
+
+ its([:requirement]) { is_expected.to eq(">=1.3,<1.6") }
+
+ context "when the requirement supports the new version" do
+ let(:setup_py_req_string) { "~=1.3" }
+
+ it { is_expected.to eq(setup_py_req) }
+ end
+
+ context "when needing an update and maintaining its precision" do
+ let(:setup_py_req_string) { "~=1.3" }
+ let(:latest_resolvable_version) { "2.1.0" }
+
+ its([:requirement]) { is_expected.to eq(">=1.3,<3.0") }
+ end
+ end
+
+ context "when a prefix match was specified" do
+ context "when the requirement is satisfied" do
+ let(:setup_py_req_string) { "==1.*.*" }
+
+ it { is_expected.to eq(setup_py_req) }
+ end
+
+ context "when needing an update" do
+ let(:setup_py_req_string) { "==1.4.*" }
+
+ its([:requirement]) { is_expected.to eq(">=1.4,<1.6") }
+ end
+
+ context "when along with an exact match" do
+ let(:setup_py_req_string) { "==1.4.*, ==1.4.1" }
+
+ its([:requirement]) { is_expected.to eq("==1.5.0") }
+ end
+ end
+ end
+ end
+
+ context "when dealing with a setup.cfg dependency" do
+ subject { updated_requirements.find { |r| r[:file] == "setup.cfg" } }
+
+ context "when there is no resolvable version" do
+ let(:latest_resolvable_version) { nil }
+
+ it { is_expected.to eq(setup_cfg_req) }
+ end
+
+ context "when there is a resolvable version" do
+ let(:latest_resolvable_version) { "1.5.0" }
+
+ context "when a full version was previously pinned" do
+ let(:setup_cfg_req_string) { "==1.4.0" }
+
+ its([:requirement]) { is_expected.to eq("==1.5.0") }
+
+ context "when the requirement has fewer digits than the new version" do
+ let(:setup_cfg_req_string) { "==1.4.0" }
+ let(:latest_resolvable_version) { "1.5.0.1" }
+
+ its([:requirement]) { is_expected.to eq("==1.5.0.1") }
+ end
+
+ context "without leading == (technically invalid)" do
+ let(:setup_cfg_req_string) { "1.4.0" }
+
+ its([:requirement]) { is_expected.to eq("1.5.0") }
+ end
+ end
+
+ context "when no requirement is specified" do
+ let(:setup_cfg_req_string) { nil }
+
+ it { is_expected.to eq(setup_cfg_req) }
+ end
+
+ context "when a range requirement was specified" do
+ let(:setup_cfg_req_string) { ">=1.3.0" }
+
+ it { is_expected.to eq(setup_cfg_req) }
+
+ context "when the requirement version is too high" do
+ let(:setup_cfg_req_string) { ">=2.0.0" }
+
+ its([:requirement]) { is_expected.to eq(:unfixable) }
+ end
+
+ context "with an upper bound" do
+ let(:setup_cfg_req_string) { ">=1.3.0, <=1.5.0" }
+
+ it { is_expected.to eq(setup_cfg_req) }
+
+ context "when needing an update" do
+ let(:setup_cfg_req_string) { ">=1.3.0, <1.5" }
+
+ its([:requirement]) { is_expected.to eq(">=1.3.0,<1.6") }
+ end
+ end
+ end
+
+ context "when a compatibility requirement was specified" do
+ let(:setup_cfg_req_string) { "~=1.3.0" }
+
+ its([:requirement]) { is_expected.to eq(">=1.3,<1.6") }
+
+ context "when the requirement supports the new version" do
+ let(:setup_cfg_req_string) { "~=1.3" }
+
+ it { is_expected.to eq(setup_cfg_req) }
+ end
+
+ context "when needing an update and maintaining its precision" do
+ let(:setup_cfg_req_string) { "~=1.3" }
+ let(:latest_resolvable_version) { "2.1.0" }
+
+ its([:requirement]) { is_expected.to eq(">=1.3,<3.0") }
+ end
+ end
+
+ context "when a prefix match was specified" do
+ context "when the requirement is satisfied" do
+ let(:setup_cfg_req_string) { "==1.*.*" }
+
+ it { is_expected.to eq(setup_cfg_req) }
+ end
+
+ context "when needing an update" do
+ let(:setup_cfg_req_string) { "==1.4.*" }
+
+ its([:requirement]) { is_expected.to eq(">=1.4,<1.6") }
+ end
+
+ context "when along with an exact match" do
+ let(:setup_cfg_req_string) { "==1.4.*, ==1.4.1" }
+
+ its([:requirement]) { is_expected.to eq("==1.5.0") }
+ end
+ end
+ end
+ end
+
+ context "when dealing with a pyproject.toml dependency" do
+ subject { updated_requirements.find { |r| r[:file] == "pyproject.toml" } }
+
+ let(:requirements) { [pyproject_req].compact }
+ let(:pyproject_req) do
+ {
+ file: "pyproject.toml",
+ requirement: pyproject_req_string,
+ groups: groups,
+ source: nil
+ }
+ end
+ let(:groups) { [] }
+
+ let(:pyproject_req_string) { "*" }
+
+ [
+ Dependabot::RequirementsUpdateStrategy::BumpVersions,
+ Dependabot::RequirementsUpdateStrategy::BumpVersionsIfNecessary
+ ].each do |update_strategy|
+ context "when asked to #{update_strategy}" do
+ let(:update_strategy) { update_strategy }
+
+ context "when there is no resolvable version" do
+ let(:latest_resolvable_version) { nil }
+
+ it { is_expected.to eq(pyproject_req) }
+ end
+
+ context "when there is a resolvable version" do
+ let(:latest_resolvable_version) { "1.5.0" }
+
+ context "when a full version was previously pinned" do
+ let(:pyproject_req_string) { "1.4.0" }
+
+ its([:requirement]) { is_expected.to eq("1.5.0") }
+
+ context "when the requirement has fewer digits than the new version" do
+ let(:pyproject_req_string) { "1.4" }
+ let(:latest_resolvable_version) { "1.5.0" }
+
+ its([:requirement]) { is_expected.to eq("1.5.0") }
+ end
+
+ context "when the requirement had a local version" do
+ let(:pyproject_req_string) { "1.4.0+gc.1" }
+
+ its([:requirement]) { is_expected.to eq("1.5.0") }
+ end
+
+ context "when using an equality matcher" do
+ let(:pyproject_req_string) { "==1.4.0" }
+
+ its([:requirement]) { is_expected.to eq("==1.5.0") }
+
+ context "with a single equals" do
+ let(:pyproject_req_string) { "=1.4.0" }
+
+ its([:requirement]) { is_expected.to eq("=1.5.0") }
+ end
+ end
+ end
+
+ context "when an asterisk was specified" do
+ let(:pyproject_req_string) { "*" }
+
+ it { is_expected.to eq(pyproject_req) }
+ end
+
+ context "when a range requirement was specified" do
+ let(:pyproject_req_string) { ">=1.3.0" }
+
+ it { is_expected.to eq(pyproject_req) }
+
+ context "when the requirement version is too high" do
+ let(:pyproject_req_string) { ">=2.0.0" }
+
+ its([:requirement]) { is_expected.to eq(:unfixable) }
+ end
+
+ context "when the requirement had a local version" do
+ let(:pyproject_req_string) { ">=1.3.0+gc.1" }
+
+ it { is_expected.to eq(pyproject_req) }
+ end
+
+ context "with an upper bound" do
+ let(:pyproject_req_string) { ">=1.3.0, <=1.5.0" }
+
+ it { is_expected.to eq(pyproject_req) }
+
+ context "when needing an update" do
+ let(:pyproject_req_string) { ">=1.3.0, <1.5" }
+
+ its([:requirement]) { is_expected.to eq(">=1.3.0,<1.6") }
+ end
+ end
+ end
+
+ context "when a ~= requirement was specified" do
+ let(:pyproject_req_string) { "~=1.3.0" }
+
+ its([:requirement]) { is_expected.to eq("~=1.5.0") }
+ end
+
+ context "when a ~ requirement was specified" do
+ let(:pyproject_req_string) { "~1.3.0" }
+
+ its([:requirement]) { is_expected.to eq("~1.5.0") }
+ end
+
+ context "when a ^ requirement was specified" do
+ let(:pyproject_req_string) { "^1.3.0" }
+
+ its([:requirement]) do
+ is_expected.to eq(
+ if update_strategy == Dependabot::RequirementsUpdateStrategy::BumpVersions
+ "^1.5.0"
+ else
+ "^1.3.0"
+ end
+ )
+ end
+
+ context "without a lockfile" do
+ let(:has_lockfile) { false }
+
+ its([:requirement]) { is_expected.to eq("^1.3.0") }
+
+ context "when needing an update" do
+ let(:latest_resolvable_version) { "2.5.0" }
+
+ its([:requirement]) { is_expected.to eq("^2.5.0") }
+ end
+ end
+
+ context "with an || specifier" do
+ let(:pyproject_req_string) { "^0.8.0 || ^1.3.0" }
+
+ its([:requirement]) { is_expected.to eq("^0.8.0 || ^1.3.0") }
+ end
+ end
+
+ context "when a wildcard match was specified" do
+ context "when the requirement is satisfied" do
+ let(:pyproject_req_string) { "==1.*.*" }
+
+ it { is_expected.to eq(pyproject_req) }
+ end
+
+ context "when needing an update" do
+ let(:pyproject_req_string) { "==1.4.*" }
+
+ its([:requirement]) { is_expected.to eq("==1.5.*") }
+ end
+
+ context "when along with an exact match" do
+ let(:pyproject_req_string) { "==1.4.*, ==1.4.1" }
+
+ its([:requirement]) { is_expected.to eq("==1.5.0") }
+ end
+ end
+ end
+ end
+ end
+
+ context "when asked to widen ranges" do
+ let(:update_strategy) { Dependabot::RequirementsUpdateStrategy::WidenRanges }
+
+ context "when there is no resolvable version" do
+ let(:latest_resolvable_version) { nil }
+
+ it { is_expected.to eq(pyproject_req) }
+ end
+
+ context "when there is a resolvable version" do
+ let(:latest_resolvable_version) { "1.5.0" }
+
+ context "when a full version was previously pinned" do
+ let(:pyproject_req_string) { "1.4.0" }
+
+ its([:requirement]) { is_expected.to eq("1.5.0") }
+
+ context "when the requirement has fewer digits than the new version" do
+ let(:pyproject_req_string) { "1.4" }
+ let(:latest_resolvable_version) { "1.5.0" }
+
+ its([:requirement]) { is_expected.to eq("1.5.0") }
+ end
+
+ context "when the requirement had a local version" do
+ let(:pyproject_req_string) { "1.4.0+gc.1" }
+
+ its([:requirement]) { is_expected.to eq("1.5.0") }
+ end
+
+ context "when using an equality matcher" do
+ let(:pyproject_req_string) { "==1.4.0" }
+
+ its([:requirement]) { is_expected.to eq("==1.5.0") }
+ end
+ end
+
+ context "when an asterisk was specified" do
+ let(:pyproject_req_string) { "*" }
+
+ it { is_expected.to eq(pyproject_req) }
+ end
+
+ context "when a range requirement was specified" do
+ let(:pyproject_req_string) { ">=1.3.0" }
+
+ it { is_expected.to eq(pyproject_req) }
+
+ context "when the requirement had a local version" do
+ let(:pyproject_req_string) { ">=1.3.0+gc.1" }
+
+ it { is_expected.to eq(pyproject_req) }
+ end
+
+ context "when the requirement is too high" do
+ let(:pyproject_req_string) { ">=2.0.0" }
+
+ its([:requirement]) { is_expected.to eq(:unfixable) }
+ end
+
+ context "with an upper bound" do
+ let(:pyproject_req_string) { ">=1.3.0, <=1.5.0" }
+
+ it { is_expected.to eq(pyproject_req) }
+
+ context "when needing an update" do
+ let(:pyproject_req_string) { ">=1.3.0, <1.5" }
+
+ its([:requirement]) { is_expected.to eq(">=1.3.0,<1.6") }
+ end
+ end
+ end
+
+ context "when a ~= requirement was specified" do
+ let(:pyproject_req_string) { "~=1.3.0" }
+
+ its([:requirement]) { is_expected.to eq(">=1.3,<1.6") }
+ end
+
+ context "when a ~ requirement was specified" do
+ let(:pyproject_req_string) { "~1.3.0" }
+
+ its([:requirement]) { is_expected.to eq(">=1.3,<1.6") }
+
+ context "when dealing with the major version" do
+ let(:pyproject_req_string) { "~1" }
+
+ its([:requirement]) { is_expected.to eq("~1") }
+
+ context "when needing an update" do
+ let(:latest_resolvable_version) { "2.5.0" }
+
+ its([:requirement]) { is_expected.to eq(">=1,<3") }
+ end
+ end
+ end
+
+ context "when a ^ requirement was specified" do
+ let(:pyproject_req_string) { "^1.3.0" }
+
+ its([:requirement]) { is_expected.to eq("^1.3.0") }
+
+ context "when dealing with a development dependency" do
+ let(:groups) { ["dev-dependencies"] }
+
+ its([:requirement]) { is_expected.to eq("^1.5.0") }
+
+ context "without a lockfile" do
+ let(:has_lockfile) { false }
+
+ its([:requirement]) { is_expected.to eq("^1.3.0") }
+ end
+ end
+
+ context "when needing an update" do
+ let(:latest_resolvable_version) { "2.5.0" }
+
+ its([:requirement]) { is_expected.to eq(">=1.3,<3.0") }
+
+ context "when the version is pre-1.0.0" do
+ let(:pyproject_req_string) { "^0.3.0" }
+ let(:latest_resolvable_version) { "0.5.0" }
+
+ its([:requirement]) { is_expected.to eq(">=0.3,<0.6") }
+ end
+
+ context "when the version is pre-0.1.0" do
+ let(:pyproject_req_string) { "^0.0.3" }
+ let(:latest_resolvable_version) { "0.0.5" }
+
+ its([:requirement]) { is_expected.to eq(">=0.0.3,<0.0.6") }
+ end
+
+ context "when dealing with a development dependency" do
+ let(:groups) { ["dev-dependencies"] }
+
+ its([:requirement]) { is_expected.to eq("^2.5.0") }
+ end
+ end
+ end
+
+ context "when a wildcard match was specified" do
+ context "when the wildcard is satisfied" do
+ let(:pyproject_req_string) { "==1.*.*" }
+
+ it { is_expected.to eq(pyproject_req) }
+ end
+
+ context "when needing an update" do
+ let(:pyproject_req_string) { "==1.4.*" }
+
+ its([:requirement]) { is_expected.to eq(">=1.4,<1.6") }
+ end
+
+ context "when along with an exact match" do
+ let(:pyproject_req_string) { "==1.4.*, ==1.4.1" }
+
+ its([:requirement]) { is_expected.to eq("==1.5.0") }
+ end
+
+ context "when part of an || condition" do
+ let(:pyproject_req_string) { "1.3.* || 1.4.*" }
+
+ its([:requirement]) do
+ is_expected.to eq("1.3.* || 1.4.* || 1.5.*")
+ end
+ end
+ end
+ end
+ end
+
+ context "when asked to not change requirements" do
+ let(:update_strategy) { Dependabot::RequirementsUpdateStrategy::LockfileOnly }
+
+ it "does not update any requirements" do
+ expect(updated_requirements).to eq(requirements)
+ end
+ end
+ end
+ end
+end
diff --git a/uv/spec/dependabot/uv/update_checker_spec.rb b/uv/spec/dependabot/uv/update_checker_spec.rb
new file mode 100644
index 00000000000..697de2a0be9
--- /dev/null
+++ b/uv/spec/dependabot/uv/update_checker_spec.rb
@@ -0,0 +1,613 @@
+# typed: false
+# frozen_string_literal: true
+
+require "spec_helper"
+
+require "dependabot/dependency_file"
+require "dependabot/dependency"
+require "dependabot/uv/update_checker"
+require "dependabot/requirements_update_strategy"
+require_common_spec "update_checkers/shared_examples_for_update_checkers"
+
+RSpec.describe Dependabot::Uv::UpdateChecker do
+ let(:dependency) { requirements_dependency }
+ let(:dependency_requirements) do
+ [{
+ file: "requirements.txt",
+ requirement: "==2.0.0",
+ groups: [],
+ source: nil
+ }]
+ end
+ let(:dependency_version) { "2.0.0" }
+ let(:dependency_name) { "luigi" }
+ let(:requirements_dependency) do
+ Dependabot::Dependency.new(
+ name: dependency_name,
+ version: dependency_version,
+ requirements: dependency_requirements,
+ package_manager: "uv"
+ )
+ end
+ let(:requirements_fixture_name) { "version_specified.txt" }
+ let(:requirements_file) do
+ Dependabot::DependencyFile.new(
+ name: "requirements.txt",
+ content: fixture("requirements", requirements_fixture_name)
+ )
+ end
+ let(:pyproject) do
+ Dependabot::DependencyFile.new(
+ name: "pyproject.toml",
+ content: fixture("pyproject_files", pyproject_fixture_name)
+ )
+ end
+ let(:dependency_files) { [requirements_file] }
+ let(:requirements_update_strategy) { nil }
+ let(:security_advisories) { [] }
+ let(:raise_on_ignored) { false }
+ let(:ignored_versions) { [] }
+ let(:credentials) do
+ [Dependabot::Credential.new({
+ "type" => "git_source",
+ "host" => "github.com",
+ "username" => "x-access-token",
+ "password" => "token"
+ })]
+ end
+ let(:checker) do
+ described_class.new(
+ dependency: dependency,
+ dependency_files: dependency_files,
+ credentials: credentials,
+ ignored_versions: ignored_versions,
+ raise_on_ignored: raise_on_ignored,
+ security_advisories: security_advisories,
+ requirements_update_strategy: requirements_update_strategy
+ )
+ end
+ let(:pypi_response) { fixture("pypi", "pypi_simple_response.html") }
+ let(:pypi_url) { "https://pypi.org/simple/luigi/" }
+
+ before do
+ stub_request(:get, pypi_url).to_return(status: 200, body: pypi_response)
+ end
+
+ it_behaves_like "an update checker"
+
+ describe "#can_update?" do
+ subject { checker.can_update?(requirements_to_unlock: :own) }
+
+ context "when the dependency is outdated" do
+ it { is_expected.to be_truthy }
+ end
+
+ context "when the dependency is up-to-date" do
+ let(:dependency_version) { "2.6.0" }
+ let(:dependency_requirements) do
+ [{
+ file: "requirements.txt",
+ requirement: "==2.6.0",
+ groups: [],
+ source: nil
+ }]
+ end
+
+ it { is_expected.to be_falsey }
+ end
+ end
+
+ describe "#latest_version" do
+ subject { checker.latest_version }
+
+ it "delegates to LatestVersionFinder" do
+ expect(described_class::LatestVersionFinder)
+ .to receive(:new)
+ .with(
+ dependency: dependency,
+ dependency_files: dependency_files,
+ credentials: credentials,
+ ignored_versions: ignored_versions,
+ raise_on_ignored: raise_on_ignored,
+ security_advisories: security_advisories
+ ).and_call_original
+ expect(checker.latest_version).to eq(Gem::Version.new("2.6.0"))
+ end
+ end
+
+ describe "#lowest_security_fix_version" do
+ subject(:lowest_fix_version) { checker.lowest_security_fix_version }
+
+ it "finds the lowest available non-vulnerable version" do
+ expect(lowest_fix_version).to eq(Gem::Version.new("2.0.1"))
+ end
+
+ context "with a security vulnerability" do
+ let(:dependency_version) { "2.0.0" }
+ let(:security_advisories) do
+ [
+ Dependabot::SecurityAdvisory.new(
+ dependency_name: dependency_name,
+ package_manager: "uv",
+ vulnerable_versions: ["<= 2.1.0"]
+ )
+ ]
+ end
+
+ it { is_expected.to eq(Gem::Version.new("2.1.1")) }
+ end
+ end
+
+ describe "#latest_resolvable_version" do
+ subject(:latest_resolvable_version) { checker.latest_resolvable_version }
+
+ context "with a requirements file only" do
+ let(:dependency_files) { [requirements_file] }
+
+ it { is_expected.to eq(Gem::Version.new("2.6.0")) }
+
+ context "when the user is ignoring the latest version" do
+ let(:ignored_versions) { [">= 2.0.0.a, < 3.0"] }
+
+ it { is_expected.to eq(Gem::Version.new("1.3.0")) }
+ end
+
+ context "when including a .python-version file" do
+ let(:dependency_files) { [requirements_file, python_version_file] }
+ let(:python_version_file) do
+ Dependabot::DependencyFile.new(
+ name: ".python-version",
+ content: python_version_content
+ )
+ end
+ let(:python_version_content) { "3.11.0\n" }
+ let(:pypi_response) do
+ fixture("pypi", "pypi_simple_response_django.html")
+ end
+ let(:pypi_url) { "https://pypi.org/simple/django/" }
+ let(:dependency_name) { "django" }
+ let(:dependency_version) { "2.2.0" }
+ let(:dependency_requirements) do
+ [{
+ file: "requirements.txt",
+ requirement: "==2.2.0",
+ groups: [],
+ source: nil
+ }]
+ end
+
+ it { is_expected.to eq(Gem::Version.new("3.2.4")) }
+
+ context "when the version is set to the oldest version of python supported by Dependabot" do
+ let(:python_version_content) { "3.9.0\n" }
+
+ it { is_expected.to eq(Gem::Version.new("3.2.4")) }
+ end
+
+ context "when the version is set to a python version no longer supported by Dependabot" do
+ let(:python_version_content) { "3.8.0\n" }
+
+ it "raises a helpful error" do
+ expect { latest_resolvable_version }.to raise_error(Dependabot::ToolVersionNotSupported) do |err|
+ expect(err.message).to start_with(
+ "Dependabot detected the following Python requirement for your project: '3.8.0'."
+ )
+ end
+ end
+ end
+ end
+ end
+
+ context "with a pip-compile file" do
+ let(:dependency_files) { [manifest_file, generated_file] }
+ let(:manifest_file) do
+ Dependabot::DependencyFile.new(
+ name: "requirements/test.in",
+ content: fixture("pip_compile_files", manifest_fixture_name)
+ )
+ end
+ let(:generated_file) do
+ Dependabot::DependencyFile.new(
+ name: "requirements/test.txt",
+ content: fixture("requirements", generated_fixture_name)
+ )
+ end
+ let(:manifest_fixture_name) { "unpinned.in" }
+ let(:generated_fixture_name) { "pip_compile_unpinned.txt" }
+ let(:dependency_requirements) do
+ [{
+ file: "requirements/test.in",
+ requirement: nil,
+ groups: [],
+ source: nil
+ }]
+ end
+
+ it "delegates to PipCompileVersionResolver" do
+ dummy_resolver =
+ instance_double(described_class::PipCompileVersionResolver)
+ allow(described_class::PipCompileVersionResolver).to receive(:new)
+ .and_return(dummy_resolver)
+ allow(dummy_resolver)
+ .to receive_messages(resolvable?: false, latest_resolvable_version: Gem::Version.new("2.5.0"))
+ expect(checker.latest_resolvable_version)
+ .to eq(Gem::Version.new("2.5.0"))
+ end
+
+ context "when a requirements.txt that specifies a subdependency" do
+ let(:dependency_files) do
+ [manifest_file, generated_file, requirements_file]
+ end
+ let(:manifest_fixture_name) { "requests.in" }
+ let(:generated_fixture_name) { "pip_compile_requests.txt" }
+ let(:requirements_fixture_name) { "urllib.txt" }
+ let(:pypi_url) { "https://pypi.org/simple/urllib3/" }
+ let(:pypi_response) do
+ fixture("pypi", "pypi_simple_response_urllib3.html")
+ end
+
+ let(:dependency_name) { "urllib3" }
+ let(:dependency_version) { "1.22" }
+ let(:dependency_requirements) do
+ [{
+ file: "requirements.txt",
+ requirement: nil,
+ groups: [],
+ source: nil
+ }]
+ end
+
+ let(:dummy_resolver) { instance_double(described_class::PipCompileVersionResolver) }
+
+ before do
+ allow(described_class::PipCompileVersionResolver).to receive(:new)
+ .and_return(dummy_resolver)
+ end
+
+ context "when the latest version is not resolvable" do
+ it "delegates to PipCompileVersionResolver" do
+ allow(dummy_resolver)
+ .to receive(:resolvable?)
+ .and_return(false)
+
+ allow(dummy_resolver)
+ .to receive(:latest_resolvable_version)
+ .with(requirement: ">=1.22,<=1.24.2")
+ .and_return(Gem::Version.new("1.24.2"))
+ expect(checker.latest_resolvable_version)
+ .to eq(Gem::Version.new("1.24.2"))
+ end
+ end
+
+ context "when the latest version is resolvable" do
+ it "returns the latest version" do
+ allow(dummy_resolver)
+ .to receive(:resolvable?)
+ .and_return(true)
+
+ expect(checker.latest_resolvable_version)
+ .to eq(Gem::Version.new("1.24.2"))
+ end
+ end
+ end
+ end
+ end
+
+ describe "#preferred_resolvable_version" do
+ subject { checker.preferred_resolvable_version }
+
+ it { is_expected.to eq(Gem::Version.new("2.6.0")) }
+
+ context "with an insecure version" do
+ let(:security_advisories) do
+ [
+ Dependabot::SecurityAdvisory.new(
+ dependency_name: dependency_name,
+ package_manager: "uv",
+ vulnerable_versions: ["<= 2.1.0"]
+ )
+ ]
+ end
+
+ it { is_expected.to eq(Gem::Version.new("2.1.1")) }
+
+ context "with a pip-compile file" do
+ let(:dependency_files) { [manifest_file, generated_file] }
+ let(:manifest_file) do
+ Dependabot::DependencyFile.new(
+ name: "requirements/test.in",
+ content: fixture("pip_compile_files", manifest_fixture_name)
+ )
+ end
+ let(:generated_file) do
+ Dependabot::DependencyFile.new(
+ name: "requirements/test.txt",
+ content: fixture("requirements", generated_fixture_name)
+ )
+ end
+ let(:manifest_fixture_name) { "unpinned.in" }
+ let(:generated_fixture_name) { "pip_compile_unpinned.txt" }
+ let(:dependency_name) { "attrs" }
+ let(:dependency_version) { "17.3.0" }
+ let(:dependency_requirements) do
+ [{
+ file: "requirements/test.in",
+ requirement: nil,
+ groups: [],
+ source: nil
+ }]
+ end
+ let(:pypi_url) { "https://pypi.org/simple/attrs/" }
+ let(:pypi_response) do
+ fixture("pypi", "pypi_simple_response_attrs.html")
+ end
+
+ let(:security_advisories) do
+ [
+ Dependabot::SecurityAdvisory.new(
+ dependency_name: dependency_name,
+ package_manager: "uv",
+ vulnerable_versions: ["< 17.4.0"]
+ )
+ ]
+ end
+
+ it { is_expected.to eq(Gem::Version.new("17.4.0")) }
+ end
+ end
+ end
+
+ describe "#latest_resolvable_version_with_no_unlock" do
+ subject { checker.send(:latest_resolvable_version_with_no_unlock) }
+
+ let(:dependency) do
+ Dependabot::Dependency.new(
+ name: "luigi",
+ version: version,
+ requirements: requirements,
+ package_manager: "uv"
+ )
+ end
+
+ context "when dealing with a requirements.txt dependency" do
+ let(:requirements) do
+ [{ file: "req.txt", requirement: req_string, groups: [], source: nil }]
+ end
+ let(:req_string) { ">=2.0.0" }
+ let(:version) { nil }
+
+ it "delegates to LatestVersionFinder" do
+ expect(described_class::LatestVersionFinder)
+ .to receive(:new)
+ .with(
+ dependency: dependency,
+ dependency_files: dependency_files,
+ credentials: credentials,
+ ignored_versions: ignored_versions,
+ raise_on_ignored: raise_on_ignored,
+ security_advisories: security_advisories
+ ).and_call_original
+ expect(checker.latest_resolvable_version_with_no_unlock)
+ .to eq(Gem::Version.new("2.6.0"))
+ end
+ end
+ end
+
+ describe "#updated_requirements" do
+ subject(:first_updated_requirements) { checker.updated_requirements.first }
+
+ its([:requirement]) { is_expected.to eq("==2.6.0") }
+
+ context "when the requirement was in a constraint file" do
+ let(:dependency) do
+ Dependabot::Dependency.new(
+ name: "luigi",
+ version: "2.0.0",
+ requirements: [{
+ file: "constraints.txt",
+ requirement: "==2.0.0",
+ groups: [],
+ source: nil
+ }],
+ package_manager: "uv"
+ )
+ end
+
+ its([:file]) { is_expected.to eq("constraints.txt") }
+ end
+
+ context "when the requirement had a lower precision" do
+ let(:dependency) do
+ Dependabot::Dependency.new(
+ name: "luigi",
+ version: "2.0",
+ requirements: [{
+ file: "requirements.txt",
+ requirement: "==2.0",
+ groups: [],
+ source: nil
+ }],
+ package_manager: "uv"
+ )
+ end
+
+ its([:requirement]) { is_expected.to eq("==2.6.0") }
+ end
+
+ context "when there is a pyproject.toml file with poetry dependencies" do
+ let(:dependency_files) { [pyproject] }
+ let(:pyproject_fixture_name) { "tilde_version.toml" }
+
+ context "when updating a dependency in an additional requirements file" do
+ let(:dependency_files) { super().append(requirements_file) }
+
+ let(:dependency) { requirements_dependency }
+
+ it "does not get affected by whether it's a library or not and updates using the :increase strategy" do
+ expect(first_updated_requirements[:requirement]).to eq("==2.6.0")
+ end
+ end
+ end
+
+ context "when there is a pyproject.toml file with standard python dependencies" do
+ let(:dependency_files) { [pyproject] }
+ let(:pyproject_fixture_name) { "standard_python_tilde_version.toml" }
+
+ context "when updating a dependency inside" do
+ let(:dependency) do
+ Dependabot::Dependency.new(
+ name: "requests",
+ version: "1.2.3",
+ requirements: [{
+ file: "pyproject.toml",
+ requirement: "~=1.0.0",
+ groups: [],
+ source: nil
+ }],
+ package_manager: "uv"
+ )
+ end
+
+ let(:pypi_url) { "https://pypi.org/simple/requests/" }
+ let(:pypi_response) do
+ fixture("pypi", "pypi_simple_response_requests.html")
+ end
+
+ context "when dealing with a library" do
+ before do
+ stub_request(:get, "https://pypi.org/pypi/pendulum/json/")
+ .to_return(
+ status: 200,
+ body: fixture("pypi", "pypi_response_pendulum.json")
+ )
+ end
+
+ its([:requirement]) { is_expected.to eq(">=1.0,<2.20") }
+ end
+
+ context "when dealing with a non-library" do
+ before do
+ stub_request(:get, "https://pypi.org/pypi/pendulum/json/")
+ .to_return(status: 404)
+ end
+
+ its([:requirement]) { is_expected.to eq("~=2.19.1") }
+ end
+ end
+
+ context "when updating a dependency in an additional requirements file" do
+ let(:dependency_files) { super().append(requirements_file) }
+
+ let(:dependency) { requirements_dependency }
+
+ it "does not get affected by whether it's a library or not and updates using the :increase strategy" do
+ expect(first_updated_requirements[:requirement]).to eq("==2.6.0")
+ end
+ end
+ end
+
+ context "when there is a pyproject.toml file with build system require dependencies" do
+ let(:dependency_files) { [pyproject] }
+ let(:pyproject_fixture_name) { "table_build_system_requires.toml" }
+
+ context "when updating a dependency inside" do
+ let(:dependency) do
+ Dependabot::Dependency.new(
+ name: "requests",
+ version: "1.2.3",
+ requirements: [{
+ file: "pyproject.toml",
+ requirement: "~=1.0.0",
+ groups: [],
+ source: nil
+ }],
+ package_manager: "uv"
+ )
+ end
+
+ let(:pypi_url) { "https://pypi.org/simple/requests/" }
+ let(:pypi_response) do
+ fixture("pypi", "pypi_simple_response_requests.html")
+ end
+
+ context "when dealing with a library" do
+ before do
+ stub_request(:get, "https://pypi.org/pypi/pendulum/json/")
+ .to_return(
+ status: 200,
+ body: fixture("pypi", "pypi_response_pendulum.json")
+ )
+ end
+
+ its([:requirement]) { is_expected.to eq(">=1.0,<2.20") }
+ end
+
+ context "when dealing with a non-library" do
+ before do
+ stub_request(:get, "https://pypi.org/pypi/pendulum/json/")
+ .to_return(status: 404)
+ end
+
+ its([:requirement]) { is_expected.to eq("~=2.19.1") }
+ end
+ end
+
+ context "when updating a dependency in an additional requirements file" do
+ let(:dependency_files) { super().append(requirements_file) }
+
+ let(:dependency) { requirements_dependency }
+
+ it "does not get affected by whether it's a library or not and updates using the :increase strategy" do
+ expect(first_updated_requirements[:requirement]).to eq("==2.6.0")
+ end
+ end
+ end
+
+ context "when there were multiple requirements" do
+ let(:dependency) do
+ Dependabot::Dependency.new(
+ name: "luigi",
+ version: "2.0.0",
+ requirements: [{
+ file: "constraints.txt",
+ requirement: "==2.0.0",
+ groups: [],
+ source: nil
+ }, {
+ file: "requirements.txt",
+ requirement: "==2.0.0",
+ groups: [],
+ source: nil
+ }],
+ package_manager: "uv"
+ )
+ end
+
+ it "updates both requirements" do
+ expect(checker.updated_requirements).to contain_exactly({
+ file: "constraints.txt",
+ requirement: "==2.6.0",
+ groups: [],
+ source: nil
+ }, {
+ file: "requirements.txt",
+ requirement: "==2.6.0",
+ groups: [],
+ source: nil
+ })
+ end
+ end
+ end
+
+ describe "#requirements_unlocked_or_can_be?" do
+ subject { checker.requirements_unlocked_or_can_be? }
+
+ it { is_expected.to be(true) }
+
+ context "with the lockfile-only requirements update strategy set" do
+ let(:requirements_update_strategy) { Dependabot::RequirementsUpdateStrategy::LockfileOnly }
+
+ it { is_expected.to be(false) }
+ end
+ end
+end
diff --git a/uv/spec/dependabot/uv/version_spec.rb b/uv/spec/dependabot/uv/version_spec.rb
new file mode 100644
index 00000000000..a5a316f23e0
--- /dev/null
+++ b/uv/spec/dependabot/uv/version_spec.rb
@@ -0,0 +1,388 @@
+# typed: false
+# frozen_string_literal: true
+
+require "spec_helper"
+require "dependabot/uv/version"
+
+RSpec.describe Dependabot::Uv::Version do
+ subject(:version) { described_class.new(version_string) }
+
+ let(:version_string) { "1.0.0" }
+
+ describe ".correct?" do
+ subject { described_class.correct?(version_string) }
+
+ context "with a valid version" do
+ let(:version_string) { "1.0.0" }
+
+ it { is_expected.to be(true) }
+
+ context "when version includes a non-zero epoch" do
+ let(:version_string) { "1!1.0.0" }
+
+ it { is_expected.to be(true) }
+ end
+
+ context "when version includes a local version" do
+ let(:version_string) { "1.0.0+abc.1" }
+
+ it { is_expected.to be(true) }
+ end
+
+ context "when version includes a prerelease part in the initial number" do
+ let(:version_string) { "2013b0" }
+
+ it { is_expected.to be(true) }
+ end
+
+ context "with a v-prefix" do
+ let(:version_string) { "v2013" }
+
+ it { is_expected.to be(true) }
+ end
+ end
+
+ context "with nil" do
+ let(:version_string) { nil }
+
+ it { is_expected.to be(false) }
+ end
+
+ context "with an empty version" do
+ let(:version_string) { "" }
+
+ it { is_expected.to be(false) }
+ end
+
+ context "with invalid versions" do
+ versions = [
+ "bad",
+ "1.0+a+",
+ "1.0++",
+ "1.0+_foobar",
+ "1.0+foo&asd",
+ "1.0+1+1",
+ "1.0.0+abc 123",
+ "v1.8.0--failed-release-attempt"
+ ]
+
+ versions.each do |version|
+ it "returns false for #{version}" do
+ expect(described_class.correct?(version)).to be false
+ end
+ end
+ end
+ end
+
+ describe ".new" do
+ subject(:version) { described_class.new(version_string) }
+
+ context "with an empty string" do
+ let(:version_string) { "" }
+ let(:error_msg) { "Malformed version string - string is empty" }
+
+ it "raises an error" do
+ expect { version }.to raise_error(Dependabot::BadRequirementError, error_msg)
+ end
+ end
+
+ context "with a nil version" do
+ let(:version_string) { nil }
+ let(:error_msg) { "Malformed version string - string is nil" }
+
+ it "raises an error" do
+ expect { version }.to raise_error(Dependabot::BadRequirementError, error_msg)
+ end
+ end
+
+ context "with a valid version" do
+ let(:version_string) { "1!1.3b2.post345.dev456" }
+
+ it "is parsed correctly" do
+ expect(version.epoch).to eq 1
+ end
+ end
+
+ context "with an invalid version" do
+ let(:version_string) { "1.0++" }
+ let(:error_msg) { "Malformed version string - #{version_string} does not match regex" }
+
+ it "raises an error" do
+ expect { version }.to raise_error(Dependabot::BadRequirementError, error_msg)
+ end
+ end
+ end
+
+ describe "#to_s" do
+ subject { version.to_s }
+
+ context "with a normal version" do
+ let(:version_string) { "1.0.0" }
+
+ it { is_expected.to eq "1.0.0" }
+ end
+
+ context "with a local version" do
+ let(:version_string) { "1.0.0+gc.1" }
+
+ it { is_expected.to eq "1.0.0+gc.1" }
+ end
+ end
+
+ describe "#<=>" do
+ sorted_versions = [
+ "0.9",
+ "1.0.0-alpha",
+ "1.0.0-a.1",
+ "1.0.0-beta",
+ "1.0.0-b.2",
+ "1.0.0-beta.11",
+ "1.0.0-rc.1",
+ "1",
+ "1.0.0+gc1",
+ "1.0.0.post", # TODO: fails comparing to 1
+ "1.post2",
+ "1.post2+gc1",
+ "1.post2+gc1.2",
+ "1.post2+gc1.11",
+ "1.0.0.post11",
+ "1.0.2",
+ "1.0.11",
+ "2016.1",
+ "1!0.1.0",
+ "2!0.1.0",
+ "10!0.1.0"
+ ]
+
+ sorted_versions.combination(2).each do |lhs, rhs|
+ it "'#{lhs}' < '#{rhs}'" do
+ expect(described_class.new(lhs)).to be < rhs
+ expect(described_class.new(rhs)).to be > lhs
+ end
+ end
+
+ sorted_versions.each do |v|
+ it "equals itself #{v}" do
+ expect(described_class.new(v)).to eq v
+ end
+ end
+
+ context "when sorting a list of versions" do
+ let(:version_strings) do
+ [
+ # Implicit epoch of 0
+ "1.0.dev456",
+ "1.0a1",
+ "1.0a2.dev456",
+ "1.0a12.dev456",
+ "1.0a12",
+ "1.0b1.dev456",
+ "1.0b2",
+ "1.0b2.post345.dev456",
+ "1.0b2.post345",
+ "1.0b2-346",
+ "1.0c1.dev456",
+ "1.0c1",
+ "1.0rc2",
+ "1.0c3",
+ "1.0",
+ "1.0.post456.dev34",
+ "1.0.post456",
+ "1.1.dev1",
+ "1.2+123abc",
+ "1.2+123abc456",
+ "1.2+abc",
+ "1.2+abc123",
+ "1.2+abc123def",
+ "1.2+1234.abc",
+ "1.2+123456",
+ "1.2.r32+123456",
+ "1.2.rev33+123456",
+ # Explicit epoch of 1
+ "1!1.0.dev456",
+ "1!1.0a1",
+ "1!1.0a2.dev456",
+ "1!1.0a12.dev456",
+ "1!1.0a12",
+ "1!1.0b1.dev456",
+ "1!1.0b2",
+ "1!1.0b2.post345.dev456",
+ "1!1.0b2.post345",
+ "1!1.0b2-346",
+ "1!1.0c1.dev456",
+ "1!1.0c1",
+ "1!1.0rc2",
+ "1!1.0c3",
+ "1!1.0",
+ "1!1.0.post456.dev34",
+ "1!1.0.post456",
+ "1!1.1.dev1",
+ "1!1.2+123abc",
+ "1!1.2+123abc456",
+ "1!1.2+abc",
+ "1!1.2+abc123",
+ "1!1.2+abc123def",
+ "1!1.2+1234.abc",
+ "1!1.2+123456",
+ "1!1.2.r32+123456",
+ "1!1.2.rev33+123456"
+ ]
+ end
+
+ let(:versions) { version_strings.map { |v| described_class.new(v) } }
+
+ it "returns list in the correct order" do
+ expect(versions.shuffle.sort).to eq versions
+ end
+ end
+
+ it "handles missing version segments" do
+ expect(described_class.new("1")).to eq "v1.0"
+ expect(described_class.new("1")).to eq "v1.0.0"
+ end
+
+ context "with different epochs" do
+ let(:version) { described_class.new("1!1.0.dev456") }
+ let(:other_version) { described_class.new("1.0.dev456") }
+
+ it "compares correctly" do
+ expect(version <=> other_version).to eq 1
+ end
+ end
+
+ context "with equivalent release candidates" do
+ let(:version) { described_class.new("1.0rc1") }
+ let(:other_version) { described_class.new("1.0c1") }
+
+ it "returns 0" do
+ expect(version <=> other_version).to eq 0
+ end
+ end
+ end
+
+ describe "#prerelease?" do
+ subject { version.prerelease? }
+
+ context "with a prerelease" do
+ versions = [
+ "1.0.dev0",
+ "1.0.dev1",
+ "1.0a1.dev1",
+ "1.0b1.dev1",
+ "1.0c1.dev1",
+ "1.0rc1.dev1",
+ "1.0a1",
+ "1.0b1",
+ "1.0c1",
+ "1.0rc1",
+ "1.0a1.post1.dev1",
+ "1.0b1.post1.dev1",
+ "1.0c1.post1.dev1",
+ "1.0rc1.post1.dev1",
+ "1.0a1.post1",
+ "1.0b1.post1",
+ "1.0c1.post1",
+ "1.0rc1.post1",
+ "1!1.0a1"
+ ]
+
+ versions.each do |version|
+ it "returns true for #{version}" do
+ expect(described_class.new(version).prerelease?).to be true
+ end
+ end
+ end
+
+ context "with a normal release" do
+ let(:version_string) { "1.0.0" }
+
+ it { is_expected.to be(false) }
+ end
+
+ context "with a post release" do
+ let(:version_string) { "1.0.0-post1" }
+
+ it { is_expected.to be(false) }
+
+ context "when version is implicit" do
+ let(:version_string) { "1.0.0-1" }
+
+ it { is_expected.to be(false) }
+ end
+
+ context "when using a dot" do
+ let(:version_string) { "1.0.0.post1" }
+
+ it { is_expected.to be(false) }
+ end
+ end
+
+ context "with a local release" do
+ let(:version_string) { "1.0+dev" }
+
+ it { is_expected.to be(false) }
+ end
+
+ context "with a local post release" do
+ let(:version_string) { "1.0.post1+dev" }
+
+ it { is_expected.to be(false) }
+ end
+ end
+
+ describe "#lowest_prerelease_suffix" do
+ subject { version.lowest_prerelease_suffix }
+
+ let(:version_string) { "1.2.3" }
+
+ it { is_expected.to eq "dev0" }
+ end
+
+ describe "#ignored_major_versions" do
+ subject(:ignored_versions) { version.ignored_major_versions }
+
+ let(:version_string) { "1.2.3-alpha.1" }
+
+ it { is_expected.to eq([">= 2.dev0"]) }
+ end
+
+ describe "#ignored_minor_versions" do
+ subject(:ignored_versions) { version.ignored_minor_versions }
+
+ let(:version_string) { "1.2.3-alpha.1" }
+
+ it { is_expected.to eq([">= 1.3.dev0, < 2.dev0"]) }
+ end
+
+ describe "#ignored_patch_versions" do
+ subject(:ignored_versions) { version.ignored_patch_versions }
+
+ let(:version_string) { "1.2.3-alpha.1" }
+
+ it { is_expected.to eq(["> #{version_string}, < 1.3.dev0"]) }
+ end
+
+ describe "compatibility with Gem::Requirement" do
+ subject { requirement.satisfied_by?(version) }
+
+ let(:requirement) { Gem::Requirement.new(">= 1.0.0") }
+
+ context "with a valid version" do
+ let(:version_string) { "1.0.0" }
+
+ it { is_expected.to be(true) }
+ end
+
+ context "with an invalid version" do
+ let(:version_string) { "0.9.0" }
+
+ it { is_expected.to be(false) }
+ end
+
+ context "with a valid local version" do
+ let(:version_string) { "1.1.0+gc.1" }
+
+ it { is_expected.to be(true) }
+ end
+ end
+end
diff --git a/uv/spec/dependabot/uv_spec.rb b/uv/spec/dependabot/uv_spec.rb
new file mode 100644
index 00000000000..35681efc2a0
--- /dev/null
+++ b/uv/spec/dependabot/uv_spec.rb
@@ -0,0 +1,10 @@
+# typed: false
+# frozen_string_literal: true
+
+require "spec_helper"
+require "dependabot/uv"
+require_common_spec "shared_examples_for_autoloading"
+
+RSpec.describe Dependabot::Uv do
+ it_behaves_like "it registers the required classes", "uv"
+end
diff --git a/uv/spec/fixtures/constraints/less_than.txt b/uv/spec/fixtures/constraints/less_than.txt
new file mode 100644
index 00000000000..cc4785d9db9
--- /dev/null
+++ b/uv/spec/fixtures/constraints/less_than.txt
@@ -0,0 +1 @@
+requests<2.0.0
diff --git a/uv/spec/fixtures/constraints/specific.txt b/uv/spec/fixtures/constraints/specific.txt
new file mode 100644
index 00000000000..4c2ec2aa09b
--- /dev/null
+++ b/uv/spec/fixtures/constraints/specific.txt
@@ -0,0 +1 @@
+requests==2.0.0
diff --git a/uv/spec/fixtures/github/contents_directory_with_outside_reference.json b/uv/spec/fixtures/github/contents_directory_with_outside_reference.json
new file mode 100644
index 00000000000..fefb56a456c
--- /dev/null
+++ b/uv/spec/fixtures/github/contents_directory_with_outside_reference.json
@@ -0,0 +1,34 @@
+[
+ {
+ "name": "base.in",
+ "path": "requirements/base.in",
+ "sha": "9d8313823765a91aa9916647d40795aac52c3dde",
+ "size": 799,
+ "url": "https://api.github.com/repos/SylinaZhang/superset-3/contents/requirements/base.in?ref=master",
+ "html_url": "https://github.com/SylinaZhang/superset-3/blob/master/requirements/base.in",
+ "git_url": "https://api.github.com/repos/SylinaZhang/superset-3/git/blobs/9d8313823765a91aa9916647d40795aac52c3dde",
+ "download_url": "https://raw.githubusercontent.com/SylinaZhang/superset-3/master/requirements/base.in",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/SylinaZhang/superset-3/contents/requirements/base.in?ref=master",
+ "git": "https://api.github.com/repos/SylinaZhang/superset-3/git/blobs/9d8313823765a91aa9916647d40795aac52c3dde",
+ "html": "https://github.com/SylinaZhang/superset-3/blob/master/requirements/base.in"
+ }
+ },
+ {
+ "name": "base.txt",
+ "path": "requirements/base.txt",
+ "sha": "1a971fdab49107704afab80fe08c52c656e292d2",
+ "size": 6494,
+ "url": "https://api.github.com/repos/SylinaZhang/superset-3/contents/requirements/base.txt?ref=master",
+ "html_url": "https://github.com/SylinaZhang/superset-3/blob/master/requirements/base.txt",
+ "git_url": "https://api.github.com/repos/SylinaZhang/superset-3/git/blobs/1a971fdab49107704afab80fe08c52c656e292d2",
+ "download_url": "https://raw.githubusercontent.com/SylinaZhang/superset-3/master/requirements/base.txt",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/SylinaZhang/superset-3/contents/requirements/base.txt?ref=master",
+ "git": "https://api.github.com/repos/SylinaZhang/superset-3/git/blobs/1a971fdab49107704afab80fe08c52c656e292d2",
+ "html": "https://github.com/SylinaZhang/superset-3/blob/master/requirements/base.txt"
+ }
+ }
+]
diff --git a/uv/spec/fixtures/github/contents_directory_with_outside_reference_in_file.json b/uv/spec/fixtures/github/contents_directory_with_outside_reference_in_file.json
new file mode 100644
index 00000000000..d2a56b38bd5
--- /dev/null
+++ b/uv/spec/fixtures/github/contents_directory_with_outside_reference_in_file.json
@@ -0,0 +1,18 @@
+{
+ "name": "base.in",
+ "path": "requirements/base.in",
+ "sha": "9d8313823765a91aa9916647d40795aac52c3dde",
+ "size": 799,
+ "url": "https://api.github.com/repos/SylinaZhang/superset-3/contents/requirements/base.in?ref=master",
+ "html_url": "https://github.com/SylinaZhang/superset-3/blob/master/requirements/base.in",
+ "git_url": "https://api.github.com/repos/SylinaZhang/superset-3/git/blobs/9d8313823765a91aa9916647d40795aac52c3dde",
+ "download_url": "https://raw.githubusercontent.com/SylinaZhang/superset-3/master/requirements/base.in",
+ "type": "file",
+ "content": "IwojIExpY2Vuc2VkIHRvIHRoZSBBcGFjaGUgU29mdHdhcmUgRm91bmRhdGlv\nbiAoQVNGKSB1bmRlciBvbmUKIyBvciBtb3JlIGNvbnRyaWJ1dG9yIGxpY2Vu\nc2UgYWdyZWVtZW50cy4gIFNlZSB0aGUgTk9USUNFIGZpbGUKIyBkaXN0cmli\ndXRlZCB3aXRoIHRoaXMgd29yayBmb3IgYWRkaXRpb25hbCBpbmZvcm1hdGlv\nbgojIHJlZ2FyZGluZyBjb3B5cmlnaHQgb3duZXJzaGlwLiAgVGhlIEFTRiBs\naWNlbnNlcyB0aGlzIGZpbGUKIyB0byB5b3UgdW5kZXIgdGhlIEFwYWNoZSBM\naWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlCiMgIkxpY2Vuc2UiKTsgeW91IG1h\neSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZQojIHdp\ndGggdGhlIExpY2Vuc2UuICBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhl\nIExpY2Vuc2UgYXQKIwojICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vu\nc2VzL0xJQ0VOU0UtMi4wCiMKIyBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGlj\nYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsCiMgc29mdHdhcmUg\nZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQg\nb24gYW4KIyAiQVMgSVMiIEJBU0lTLCBXSVRIT1VUIFdBUlJBTlRJRVMgT1Ig\nQ09ORElUSU9OUyBPRiBBTlkKIyBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBp\nbXBsaWVkLiAgU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUKIyBzcGVjaWZpYyBs\nYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kIGxpbWl0YXRpb25z\nCiMgdW5kZXIgdGhlIExpY2Vuc2UuCiMKLWUgZmlsZTouCg==\n",
+ "encoding": "base64",
+ "_links": {
+ "self": "https://api.github.com/repos/SylinaZhang/superset-3/contents/requirements/base.in?ref=master",
+ "git": "https://api.github.com/repos/SylinaZhang/superset-3/git/blobs/9d8313823765a91aa9916647d40795aac52c3dde",
+ "html": "https://github.com/SylinaZhang/superset-3/blob/master/requirements/base.in"
+ }
+}
diff --git a/uv/spec/fixtures/github/contents_directory_with_outside_reference_root.json b/uv/spec/fixtures/github/contents_directory_with_outside_reference_root.json
new file mode 100644
index 00000000000..395a5bfa5af
--- /dev/null
+++ b/uv/spec/fixtures/github/contents_directory_with_outside_reference_root.json
@@ -0,0 +1,722 @@
+[
+ {
+ "name": ".asf.yaml",
+ "path": ".asf.yaml",
+ "sha": "ab980e0c3fb2b3ef40e2dae888601e15608849b5",
+ "size": 2423,
+ "url": "https://api.github.com/repos/SylinaZhang/superset-3/contents/.asf.yaml?ref=master",
+ "html_url": "https://github.com/SylinaZhang/superset-3/blob/master/.asf.yaml",
+ "git_url": "https://api.github.com/repos/SylinaZhang/superset-3/git/blobs/ab980e0c3fb2b3ef40e2dae888601e15608849b5",
+ "download_url": "https://raw.githubusercontent.com/SylinaZhang/superset-3/master/.asf.yaml",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/SylinaZhang/superset-3/contents/.asf.yaml?ref=master",
+ "git": "https://api.github.com/repos/SylinaZhang/superset-3/git/blobs/ab980e0c3fb2b3ef40e2dae888601e15608849b5",
+ "html": "https://github.com/SylinaZhang/superset-3/blob/master/.asf.yaml"
+ }
+ },
+ {
+ "name": ".codecov.yml",
+ "path": ".codecov.yml",
+ "sha": "149042367ab18c0367e14ffebaeeb5ddecb29308",
+ "size": 911,
+ "url": "https://api.github.com/repos/SylinaZhang/superset-3/contents/.codecov.yml?ref=master",
+ "html_url": "https://github.com/SylinaZhang/superset-3/blob/master/.codecov.yml",
+ "git_url": "https://api.github.com/repos/SylinaZhang/superset-3/git/blobs/149042367ab18c0367e14ffebaeeb5ddecb29308",
+ "download_url": "https://raw.githubusercontent.com/SylinaZhang/superset-3/master/.codecov.yml",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/SylinaZhang/superset-3/contents/.codecov.yml?ref=master",
+ "git": "https://api.github.com/repos/SylinaZhang/superset-3/git/blobs/149042367ab18c0367e14ffebaeeb5ddecb29308",
+ "html": "https://github.com/SylinaZhang/superset-3/blob/master/.codecov.yml"
+ }
+ },
+ {
+ "name": ".dockerignore",
+ "path": ".dockerignore",
+ "sha": "e79b8f6e1e78f7360eef973fd002d51b94c62902",
+ "size": 1218,
+ "url": "https://api.github.com/repos/SylinaZhang/superset-3/contents/.dockerignore?ref=master",
+ "html_url": "https://github.com/SylinaZhang/superset-3/blob/master/.dockerignore",
+ "git_url": "https://api.github.com/repos/SylinaZhang/superset-3/git/blobs/e79b8f6e1e78f7360eef973fd002d51b94c62902",
+ "download_url": "https://raw.githubusercontent.com/SylinaZhang/superset-3/master/.dockerignore",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/SylinaZhang/superset-3/contents/.dockerignore?ref=master",
+ "git": "https://api.github.com/repos/SylinaZhang/superset-3/git/blobs/e79b8f6e1e78f7360eef973fd002d51b94c62902",
+ "html": "https://github.com/SylinaZhang/superset-3/blob/master/.dockerignore"
+ }
+ },
+ {
+ "name": ".editorconfig",
+ "path": ".editorconfig",
+ "sha": "dc17b28420db6d2dcb6a4b700e9993e66cb8962a",
+ "size": 1365,
+ "url": "https://api.github.com/repos/SylinaZhang/superset-3/contents/.editorconfig?ref=master",
+ "html_url": "https://github.com/SylinaZhang/superset-3/blob/master/.editorconfig",
+ "git_url": "https://api.github.com/repos/SylinaZhang/superset-3/git/blobs/dc17b28420db6d2dcb6a4b700e9993e66cb8962a",
+ "download_url": "https://raw.githubusercontent.com/SylinaZhang/superset-3/master/.editorconfig",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/SylinaZhang/superset-3/contents/.editorconfig?ref=master",
+ "git": "https://api.github.com/repos/SylinaZhang/superset-3/git/blobs/dc17b28420db6d2dcb6a4b700e9993e66cb8962a",
+ "html": "https://github.com/SylinaZhang/superset-3/blob/master/.editorconfig"
+ }
+ },
+ {
+ "name": ".flaskenv",
+ "path": ".flaskenv",
+ "sha": "5ed928d76a51a842e06bafd362c548e570555db0",
+ "size": 839,
+ "url": "https://api.github.com/repos/SylinaZhang/superset-3/contents/.flaskenv?ref=master",
+ "html_url": "https://github.com/SylinaZhang/superset-3/blob/master/.flaskenv",
+ "git_url": "https://api.github.com/repos/SylinaZhang/superset-3/git/blobs/5ed928d76a51a842e06bafd362c548e570555db0",
+ "download_url": "https://raw.githubusercontent.com/SylinaZhang/superset-3/master/.flaskenv",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/SylinaZhang/superset-3/contents/.flaskenv?ref=master",
+ "git": "https://api.github.com/repos/SylinaZhang/superset-3/git/blobs/5ed928d76a51a842e06bafd362c548e570555db0",
+ "html": "https://github.com/SylinaZhang/superset-3/blob/master/.flaskenv"
+ }
+ },
+ {
+ "name": ".fossa.yml",
+ "path": ".fossa.yml",
+ "sha": "974aa72e7da636ccf7f60da1f2b61e32a4a374fd",
+ "size": 1176,
+ "url": "https://api.github.com/repos/SylinaZhang/superset-3/contents/.fossa.yml?ref=master",
+ "html_url": "https://github.com/SylinaZhang/superset-3/blob/master/.fossa.yml",
+ "git_url": "https://api.github.com/repos/SylinaZhang/superset-3/git/blobs/974aa72e7da636ccf7f60da1f2b61e32a4a374fd",
+ "download_url": "https://raw.githubusercontent.com/SylinaZhang/superset-3/master/.fossa.yml",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/SylinaZhang/superset-3/contents/.fossa.yml?ref=master",
+ "git": "https://api.github.com/repos/SylinaZhang/superset-3/git/blobs/974aa72e7da636ccf7f60da1f2b61e32a4a374fd",
+ "html": "https://github.com/SylinaZhang/superset-3/blob/master/.fossa.yml"
+ }
+ },
+ {
+ "name": ".gitattributes",
+ "path": ".gitattributes",
+ "sha": "79f44a6b263773835c3690f3014e08ac5b08fcea",
+ "size": 27,
+ "url": "https://api.github.com/repos/SylinaZhang/superset-3/contents/.gitattributes?ref=master",
+ "html_url": "https://github.com/SylinaZhang/superset-3/blob/master/.gitattributes",
+ "git_url": "https://api.github.com/repos/SylinaZhang/superset-3/git/blobs/79f44a6b263773835c3690f3014e08ac5b08fcea",
+ "download_url": "https://raw.githubusercontent.com/SylinaZhang/superset-3/master/.gitattributes",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/SylinaZhang/superset-3/contents/.gitattributes?ref=master",
+ "git": "https://api.github.com/repos/SylinaZhang/superset-3/git/blobs/79f44a6b263773835c3690f3014e08ac5b08fcea",
+ "html": "https://github.com/SylinaZhang/superset-3/blob/master/.gitattributes"
+ }
+ },
+ {
+ "name": ".github",
+ "path": ".github",
+ "sha": "52fcc57aeb19a7d59f425cbcede2270b6cdb6413",
+ "size": 0,
+ "url": "https://api.github.com/repos/SylinaZhang/superset-3/contents/.github?ref=master",
+ "html_url": "https://github.com/SylinaZhang/superset-3/tree/master/.github",
+ "git_url": "https://api.github.com/repos/SylinaZhang/superset-3/git/trees/52fcc57aeb19a7d59f425cbcede2270b6cdb6413",
+ "download_url": null,
+ "type": "dir",
+ "_links": {
+ "self": "https://api.github.com/repos/SylinaZhang/superset-3/contents/.github?ref=master",
+ "git": "https://api.github.com/repos/SylinaZhang/superset-3/git/trees/52fcc57aeb19a7d59f425cbcede2270b6cdb6413",
+ "html": "https://github.com/SylinaZhang/superset-3/tree/master/.github"
+ }
+ },
+ {
+ "name": ".gitignore",
+ "path": ".gitignore",
+ "sha": "a23cbb9ba5a6e630dc77f64ee203f34936570c51",
+ "size": 2003,
+ "url": "https://api.github.com/repos/SylinaZhang/superset-3/contents/.gitignore?ref=master",
+ "html_url": "https://github.com/SylinaZhang/superset-3/blob/master/.gitignore",
+ "git_url": "https://api.github.com/repos/SylinaZhang/superset-3/git/blobs/a23cbb9ba5a6e630dc77f64ee203f34936570c51",
+ "download_url": "https://raw.githubusercontent.com/SylinaZhang/superset-3/master/.gitignore",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/SylinaZhang/superset-3/contents/.gitignore?ref=master",
+ "git": "https://api.github.com/repos/SylinaZhang/superset-3/git/blobs/a23cbb9ba5a6e630dc77f64ee203f34936570c51",
+ "html": "https://github.com/SylinaZhang/superset-3/blob/master/.gitignore"
+ }
+ },
+ {
+ "name": ".gitmodules",
+ "path": ".gitmodules",
+ "sha": "bf3f8a1b37ea785c58bfbbb3d2c23e6dbe67dd6f",
+ "size": 1985,
+ "url": "https://api.github.com/repos/SylinaZhang/superset-3/contents/.gitmodules?ref=master",
+ "html_url": "https://github.com/SylinaZhang/superset-3/blob/master/.gitmodules",
+ "git_url": "https://api.github.com/repos/SylinaZhang/superset-3/git/blobs/bf3f8a1b37ea785c58bfbbb3d2c23e6dbe67dd6f",
+ "download_url": "https://raw.githubusercontent.com/SylinaZhang/superset-3/master/.gitmodules",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/SylinaZhang/superset-3/contents/.gitmodules?ref=master",
+ "git": "https://api.github.com/repos/SylinaZhang/superset-3/git/blobs/bf3f8a1b37ea785c58bfbbb3d2c23e6dbe67dd6f",
+ "html": "https://github.com/SylinaZhang/superset-3/blob/master/.gitmodules"
+ }
+ },
+ {
+ "name": ".markdownlint.json",
+ "path": ".markdownlint.json",
+ "sha": "dcc40721cea282bde13a400dd6130900df229c1c",
+ "size": 52,
+ "url": "https://api.github.com/repos/SylinaZhang/superset-3/contents/.markdownlint.json?ref=master",
+ "html_url": "https://github.com/SylinaZhang/superset-3/blob/master/.markdownlint.json",
+ "git_url": "https://api.github.com/repos/SylinaZhang/superset-3/git/blobs/dcc40721cea282bde13a400dd6130900df229c1c",
+ "download_url": "https://raw.githubusercontent.com/SylinaZhang/superset-3/master/.markdownlint.json",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/SylinaZhang/superset-3/contents/.markdownlint.json?ref=master",
+ "git": "https://api.github.com/repos/SylinaZhang/superset-3/git/blobs/dcc40721cea282bde13a400dd6130900df229c1c",
+ "html": "https://github.com/SylinaZhang/superset-3/blob/master/.markdownlint.json"
+ }
+ },
+ {
+ "name": ".pre-commit-config.yaml",
+ "path": ".pre-commit-config.yaml",
+ "sha": "9e0318456deeabeeaa5367673c5493cce2301db0",
+ "size": 3248,
+ "url": "https://api.github.com/repos/SylinaZhang/superset-3/contents/.pre-commit-config.yaml?ref=master",
+ "html_url": "https://github.com/SylinaZhang/superset-3/blob/master/.pre-commit-config.yaml",
+ "git_url": "https://api.github.com/repos/SylinaZhang/superset-3/git/blobs/9e0318456deeabeeaa5367673c5493cce2301db0",
+ "download_url": "https://raw.githubusercontent.com/SylinaZhang/superset-3/master/.pre-commit-config.yaml",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/SylinaZhang/superset-3/contents/.pre-commit-config.yaml?ref=master",
+ "git": "https://api.github.com/repos/SylinaZhang/superset-3/git/blobs/9e0318456deeabeeaa5367673c5493cce2301db0",
+ "html": "https://github.com/SylinaZhang/superset-3/blob/master/.pre-commit-config.yaml"
+ }
+ },
+ {
+ "name": ".pylintrc",
+ "path": ".pylintrc",
+ "sha": "08e44d3fae390fa4a1318f7e45c5700b3cb07877",
+ "size": 14279,
+ "url": "https://api.github.com/repos/SylinaZhang/superset-3/contents/.pylintrc?ref=master",
+ "html_url": "https://github.com/SylinaZhang/superset-3/blob/master/.pylintrc",
+ "git_url": "https://api.github.com/repos/SylinaZhang/superset-3/git/blobs/08e44d3fae390fa4a1318f7e45c5700b3cb07877",
+ "download_url": "https://raw.githubusercontent.com/SylinaZhang/superset-3/master/.pylintrc",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/SylinaZhang/superset-3/contents/.pylintrc?ref=master",
+ "git": "https://api.github.com/repos/SylinaZhang/superset-3/git/blobs/08e44d3fae390fa4a1318f7e45c5700b3cb07877",
+ "html": "https://github.com/SylinaZhang/superset-3/blob/master/.pylintrc"
+ }
+ },
+ {
+ "name": ".rat-excludes",
+ "path": ".rat-excludes",
+ "sha": "f50d6a3862082fdc8443397dbdc8ce16de3288c0",
+ "size": 861,
+ "url": "https://api.github.com/repos/SylinaZhang/superset-3/contents/.rat-excludes?ref=master",
+ "html_url": "https://github.com/SylinaZhang/superset-3/blob/master/.rat-excludes",
+ "git_url": "https://api.github.com/repos/SylinaZhang/superset-3/git/blobs/f50d6a3862082fdc8443397dbdc8ce16de3288c0",
+ "download_url": "https://raw.githubusercontent.com/SylinaZhang/superset-3/master/.rat-excludes",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/SylinaZhang/superset-3/contents/.rat-excludes?ref=master",
+ "git": "https://api.github.com/repos/SylinaZhang/superset-3/git/blobs/f50d6a3862082fdc8443397dbdc8ce16de3288c0",
+ "html": "https://github.com/SylinaZhang/superset-3/blob/master/.rat-excludes"
+ }
+ },
+ {
+ "name": "CHANGELOG.md",
+ "path": "CHANGELOG.md",
+ "sha": "55656a16ab6ac6282c7c2a9cd9a92158dad5a88c",
+ "size": 426589,
+ "url": "https://api.github.com/repos/SylinaZhang/superset-3/contents/CHANGELOG.md?ref=master",
+ "html_url": "https://github.com/SylinaZhang/superset-3/blob/master/CHANGELOG.md",
+ "git_url": "https://api.github.com/repos/SylinaZhang/superset-3/git/blobs/55656a16ab6ac6282c7c2a9cd9a92158dad5a88c",
+ "download_url": "https://raw.githubusercontent.com/SylinaZhang/superset-3/master/CHANGELOG.md",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/SylinaZhang/superset-3/contents/CHANGELOG.md?ref=master",
+ "git": "https://api.github.com/repos/SylinaZhang/superset-3/git/blobs/55656a16ab6ac6282c7c2a9cd9a92158dad5a88c",
+ "html": "https://github.com/SylinaZhang/superset-3/blob/master/CHANGELOG.md"
+ }
+ },
+ {
+ "name": "CODE_OF_CONDUCT.md",
+ "path": "CODE_OF_CONDUCT.md",
+ "sha": "a328cf44d770647d74e53d52e6adb8877988cd2f",
+ "size": 12805,
+ "url": "https://api.github.com/repos/SylinaZhang/superset-3/contents/CODE_OF_CONDUCT.md?ref=master",
+ "html_url": "https://github.com/SylinaZhang/superset-3/blob/master/CODE_OF_CONDUCT.md",
+ "git_url": "https://api.github.com/repos/SylinaZhang/superset-3/git/blobs/a328cf44d770647d74e53d52e6adb8877988cd2f",
+ "download_url": "https://raw.githubusercontent.com/SylinaZhang/superset-3/master/CODE_OF_CONDUCT.md",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/SylinaZhang/superset-3/contents/CODE_OF_CONDUCT.md?ref=master",
+ "git": "https://api.github.com/repos/SylinaZhang/superset-3/git/blobs/a328cf44d770647d74e53d52e6adb8877988cd2f",
+ "html": "https://github.com/SylinaZhang/superset-3/blob/master/CODE_OF_CONDUCT.md"
+ }
+ },
+ {
+ "name": "CONTRIBUTING.md",
+ "path": "CONTRIBUTING.md",
+ "sha": "94573f2a9e3f420d720248e1074bb17fac27c1c6",
+ "size": 75361,
+ "url": "https://api.github.com/repos/SylinaZhang/superset-3/contents/CONTRIBUTING.md?ref=master",
+ "html_url": "https://github.com/SylinaZhang/superset-3/blob/master/CONTRIBUTING.md",
+ "git_url": "https://api.github.com/repos/SylinaZhang/superset-3/git/blobs/94573f2a9e3f420d720248e1074bb17fac27c1c6",
+ "download_url": "https://raw.githubusercontent.com/SylinaZhang/superset-3/master/CONTRIBUTING.md",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/SylinaZhang/superset-3/contents/CONTRIBUTING.md?ref=master",
+ "git": "https://api.github.com/repos/SylinaZhang/superset-3/git/blobs/94573f2a9e3f420d720248e1074bb17fac27c1c6",
+ "html": "https://github.com/SylinaZhang/superset-3/blob/master/CONTRIBUTING.md"
+ }
+ },
+ {
+ "name": "Dockerfile",
+ "path": "Dockerfile",
+ "sha": "3f6152e763abd390c94ed7eb6f08805ae26b4bac",
+ "size": 5141,
+ "url": "https://api.github.com/repos/SylinaZhang/superset-3/contents/Dockerfile?ref=master",
+ "html_url": "https://github.com/SylinaZhang/superset-3/blob/master/Dockerfile",
+ "git_url": "https://api.github.com/repos/SylinaZhang/superset-3/git/blobs/3f6152e763abd390c94ed7eb6f08805ae26b4bac",
+ "download_url": "https://raw.githubusercontent.com/SylinaZhang/superset-3/master/Dockerfile",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/SylinaZhang/superset-3/contents/Dockerfile?ref=master",
+ "git": "https://api.github.com/repos/SylinaZhang/superset-3/git/blobs/3f6152e763abd390c94ed7eb6f08805ae26b4bac",
+ "html": "https://github.com/SylinaZhang/superset-3/blob/master/Dockerfile"
+ }
+ },
+ {
+ "name": "INSTALL.md",
+ "path": "INSTALL.md",
+ "sha": "afe091241f8acf5d077bd9c562bb0973e1a776af",
+ "size": 978,
+ "url": "https://api.github.com/repos/SylinaZhang/superset-3/contents/INSTALL.md?ref=master",
+ "html_url": "https://github.com/SylinaZhang/superset-3/blob/master/INSTALL.md",
+ "git_url": "https://api.github.com/repos/SylinaZhang/superset-3/git/blobs/afe091241f8acf5d077bd9c562bb0973e1a776af",
+ "download_url": "https://raw.githubusercontent.com/SylinaZhang/superset-3/master/INSTALL.md",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/SylinaZhang/superset-3/contents/INSTALL.md?ref=master",
+ "git": "https://api.github.com/repos/SylinaZhang/superset-3/git/blobs/afe091241f8acf5d077bd9c562bb0973e1a776af",
+ "html": "https://github.com/SylinaZhang/superset-3/blob/master/INSTALL.md"
+ }
+ },
+ {
+ "name": "LICENSE.txt",
+ "path": "LICENSE.txt",
+ "sha": "56313ab5a54a163e7d46224cb5470a814c3a2436",
+ "size": 11585,
+ "url": "https://api.github.com/repos/SylinaZhang/superset-3/contents/LICENSE.txt?ref=master",
+ "html_url": "https://github.com/SylinaZhang/superset-3/blob/master/LICENSE.txt",
+ "git_url": "https://api.github.com/repos/SylinaZhang/superset-3/git/blobs/56313ab5a54a163e7d46224cb5470a814c3a2436",
+ "download_url": "https://raw.githubusercontent.com/SylinaZhang/superset-3/master/LICENSE.txt",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/SylinaZhang/superset-3/contents/LICENSE.txt?ref=master",
+ "git": "https://api.github.com/repos/SylinaZhang/superset-3/git/blobs/56313ab5a54a163e7d46224cb5470a814c3a2436",
+ "html": "https://github.com/SylinaZhang/superset-3/blob/master/LICENSE.txt"
+ }
+ },
+ {
+ "name": "MANIFEST.in",
+ "path": "MANIFEST.in",
+ "sha": "4d7a98b2a7ac8c82f6d58df5fbd6db697c28c5b2",
+ "size": 1113,
+ "url": "https://api.github.com/repos/SylinaZhang/superset-3/contents/MANIFEST.in?ref=master",
+ "html_url": "https://github.com/SylinaZhang/superset-3/blob/master/MANIFEST.in",
+ "git_url": "https://api.github.com/repos/SylinaZhang/superset-3/git/blobs/4d7a98b2a7ac8c82f6d58df5fbd6db697c28c5b2",
+ "download_url": "https://raw.githubusercontent.com/SylinaZhang/superset-3/master/MANIFEST.in",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/SylinaZhang/superset-3/contents/MANIFEST.in?ref=master",
+ "git": "https://api.github.com/repos/SylinaZhang/superset-3/git/blobs/4d7a98b2a7ac8c82f6d58df5fbd6db697c28c5b2",
+ "html": "https://github.com/SylinaZhang/superset-3/blob/master/MANIFEST.in"
+ }
+ },
+ {
+ "name": "Makefile",
+ "path": "Makefile",
+ "sha": "14e7bb17efdac01eae897ba455bb4b287f30a719",
+ "size": 3291,
+ "url": "https://api.github.com/repos/SylinaZhang/superset-3/contents/Makefile?ref=master",
+ "html_url": "https://github.com/SylinaZhang/superset-3/blob/master/Makefile",
+ "git_url": "https://api.github.com/repos/SylinaZhang/superset-3/git/blobs/14e7bb17efdac01eae897ba455bb4b287f30a719",
+ "download_url": "https://raw.githubusercontent.com/SylinaZhang/superset-3/master/Makefile",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/SylinaZhang/superset-3/contents/Makefile?ref=master",
+ "git": "https://api.github.com/repos/SylinaZhang/superset-3/git/blobs/14e7bb17efdac01eae897ba455bb4b287f30a719",
+ "html": "https://github.com/SylinaZhang/superset-3/blob/master/Makefile"
+ }
+ },
+ {
+ "name": "NOTICE",
+ "path": "NOTICE",
+ "sha": "32faddf7066d7e199991b0259e4b05faea5951c5",
+ "size": 169,
+ "url": "https://api.github.com/repos/SylinaZhang/superset-3/contents/NOTICE?ref=master",
+ "html_url": "https://github.com/SylinaZhang/superset-3/blob/master/NOTICE",
+ "git_url": "https://api.github.com/repos/SylinaZhang/superset-3/git/blobs/32faddf7066d7e199991b0259e4b05faea5951c5",
+ "download_url": "https://raw.githubusercontent.com/SylinaZhang/superset-3/master/NOTICE",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/SylinaZhang/superset-3/contents/NOTICE?ref=master",
+ "git": "https://api.github.com/repos/SylinaZhang/superset-3/git/blobs/32faddf7066d7e199991b0259e4b05faea5951c5",
+ "html": "https://github.com/SylinaZhang/superset-3/blob/master/NOTICE"
+ }
+ },
+ {
+ "name": "README.md",
+ "path": "README.md",
+ "sha": "8c13452d18d6cbd0e86bc9e30b6a0c62c9dc72e3",
+ "size": 11793,
+ "url": "https://api.github.com/repos/SylinaZhang/superset-3/contents/README.md?ref=master",
+ "html_url": "https://github.com/SylinaZhang/superset-3/blob/master/README.md",
+ "git_url": "https://api.github.com/repos/SylinaZhang/superset-3/git/blobs/8c13452d18d6cbd0e86bc9e30b6a0c62c9dc72e3",
+ "download_url": "https://raw.githubusercontent.com/SylinaZhang/superset-3/master/README.md",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/SylinaZhang/superset-3/contents/README.md?ref=master",
+ "git": "https://api.github.com/repos/SylinaZhang/superset-3/git/blobs/8c13452d18d6cbd0e86bc9e30b6a0c62c9dc72e3",
+ "html": "https://github.com/SylinaZhang/superset-3/blob/master/README.md"
+ }
+ },
+ {
+ "name": "RELEASING",
+ "path": "RELEASING",
+ "sha": "b1618af4d26d477767b0071e92e4a2ea63f045d4",
+ "size": 0,
+ "url": "https://api.github.com/repos/SylinaZhang/superset-3/contents/RELEASING?ref=master",
+ "html_url": "https://github.com/SylinaZhang/superset-3/tree/master/RELEASING",
+ "git_url": "https://api.github.com/repos/SylinaZhang/superset-3/git/trees/b1618af4d26d477767b0071e92e4a2ea63f045d4",
+ "download_url": null,
+ "type": "dir",
+ "_links": {
+ "self": "https://api.github.com/repos/SylinaZhang/superset-3/contents/RELEASING?ref=master",
+ "git": "https://api.github.com/repos/SylinaZhang/superset-3/git/trees/b1618af4d26d477767b0071e92e4a2ea63f045d4",
+ "html": "https://github.com/SylinaZhang/superset-3/tree/master/RELEASING"
+ }
+ },
+ {
+ "name": "RESOURCES",
+ "path": "RESOURCES",
+ "sha": "2c6a7ba6e7f2a1051a89bcb785decb523fb01d4d",
+ "size": 0,
+ "url": "https://api.github.com/repos/SylinaZhang/superset-3/contents/RESOURCES?ref=master",
+ "html_url": "https://github.com/SylinaZhang/superset-3/tree/master/RESOURCES",
+ "git_url": "https://api.github.com/repos/SylinaZhang/superset-3/git/trees/2c6a7ba6e7f2a1051a89bcb785decb523fb01d4d",
+ "download_url": null,
+ "type": "dir",
+ "_links": {
+ "self": "https://api.github.com/repos/SylinaZhang/superset-3/contents/RESOURCES?ref=master",
+ "git": "https://api.github.com/repos/SylinaZhang/superset-3/git/trees/2c6a7ba6e7f2a1051a89bcb785decb523fb01d4d",
+ "html": "https://github.com/SylinaZhang/superset-3/tree/master/RESOURCES"
+ }
+ },
+ {
+ "name": "UPDATING.md",
+ "path": "UPDATING.md",
+ "sha": "e133bf257c8c9fdf10574f5bdce6cf7f7ae1bf58",
+ "size": 59308,
+ "url": "https://api.github.com/repos/SylinaZhang/superset-3/contents/UPDATING.md?ref=master",
+ "html_url": "https://github.com/SylinaZhang/superset-3/blob/master/UPDATING.md",
+ "git_url": "https://api.github.com/repos/SylinaZhang/superset-3/git/blobs/e133bf257c8c9fdf10574f5bdce6cf7f7ae1bf58",
+ "download_url": "https://raw.githubusercontent.com/SylinaZhang/superset-3/master/UPDATING.md",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/SylinaZhang/superset-3/contents/UPDATING.md?ref=master",
+ "git": "https://api.github.com/repos/SylinaZhang/superset-3/git/blobs/e133bf257c8c9fdf10574f5bdce6cf7f7ae1bf58",
+ "html": "https://github.com/SylinaZhang/superset-3/blob/master/UPDATING.md"
+ }
+ },
+ {
+ "name": "docker-compose-non-dev.yml",
+ "path": "docker-compose-non-dev.yml",
+ "sha": "785472e7c6a1c150978f0656342fd98761052053",
+ "size": 3012,
+ "url": "https://api.github.com/repos/SylinaZhang/superset-3/contents/docker-compose-non-dev.yml?ref=master",
+ "html_url": "https://github.com/SylinaZhang/superset-3/blob/master/docker-compose-non-dev.yml",
+ "git_url": "https://api.github.com/repos/SylinaZhang/superset-3/git/blobs/785472e7c6a1c150978f0656342fd98761052053",
+ "download_url": "https://raw.githubusercontent.com/SylinaZhang/superset-3/master/docker-compose-non-dev.yml",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/SylinaZhang/superset-3/contents/docker-compose-non-dev.yml?ref=master",
+ "git": "https://api.github.com/repos/SylinaZhang/superset-3/git/blobs/785472e7c6a1c150978f0656342fd98761052053",
+ "html": "https://github.com/SylinaZhang/superset-3/blob/master/docker-compose-non-dev.yml"
+ }
+ },
+ {
+ "name": "docker-compose.yml",
+ "path": "docker-compose.yml",
+ "sha": "3f9c99f21fea74882e2ba2702234af3e793bc049",
+ "size": 5184,
+ "url": "https://api.github.com/repos/SylinaZhang/superset-3/contents/docker-compose.yml?ref=master",
+ "html_url": "https://github.com/SylinaZhang/superset-3/blob/master/docker-compose.yml",
+ "git_url": "https://api.github.com/repos/SylinaZhang/superset-3/git/blobs/3f9c99f21fea74882e2ba2702234af3e793bc049",
+ "download_url": "https://raw.githubusercontent.com/SylinaZhang/superset-3/master/docker-compose.yml",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/SylinaZhang/superset-3/contents/docker-compose.yml?ref=master",
+ "git": "https://api.github.com/repos/SylinaZhang/superset-3/git/blobs/3f9c99f21fea74882e2ba2702234af3e793bc049",
+ "html": "https://github.com/SylinaZhang/superset-3/blob/master/docker-compose.yml"
+ }
+ },
+ {
+ "name": "docker",
+ "path": "docker",
+ "sha": "378b47d500db2c3d7378c4e12632e1a4c0cc9db5",
+ "size": 0,
+ "url": "https://api.github.com/repos/SylinaZhang/superset-3/contents/docker?ref=master",
+ "html_url": "https://github.com/SylinaZhang/superset-3/tree/master/docker",
+ "git_url": "https://api.github.com/repos/SylinaZhang/superset-3/git/trees/378b47d500db2c3d7378c4e12632e1a4c0cc9db5",
+ "download_url": null,
+ "type": "dir",
+ "_links": {
+ "self": "https://api.github.com/repos/SylinaZhang/superset-3/contents/docker?ref=master",
+ "git": "https://api.github.com/repos/SylinaZhang/superset-3/git/trees/378b47d500db2c3d7378c4e12632e1a4c0cc9db5",
+ "html": "https://github.com/SylinaZhang/superset-3/tree/master/docker"
+ }
+ },
+ {
+ "name": "dockerize.Dockerfile",
+ "path": "dockerize.Dockerfile",
+ "sha": "4a3fa1b6f25ddedb45821728fc75de75f5ff0929",
+ "size": 363,
+ "url": "https://api.github.com/repos/SylinaZhang/superset-3/contents/dockerize.Dockerfile?ref=master",
+ "html_url": "https://github.com/SylinaZhang/superset-3/blob/master/dockerize.Dockerfile",
+ "git_url": "https://api.github.com/repos/SylinaZhang/superset-3/git/blobs/4a3fa1b6f25ddedb45821728fc75de75f5ff0929",
+ "download_url": "https://raw.githubusercontent.com/SylinaZhang/superset-3/master/dockerize.Dockerfile",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/SylinaZhang/superset-3/contents/dockerize.Dockerfile?ref=master",
+ "git": "https://api.github.com/repos/SylinaZhang/superset-3/git/blobs/4a3fa1b6f25ddedb45821728fc75de75f5ff0929",
+ "html": "https://github.com/SylinaZhang/superset-3/blob/master/dockerize.Dockerfile"
+ }
+ },
+ {
+ "name": "docs",
+ "path": "docs",
+ "sha": "c392f0e790ae8df54eb1b9527852c71d67631428",
+ "size": 0,
+ "url": "https://api.github.com/repos/SylinaZhang/superset-3/contents/docs?ref=master",
+ "html_url": "https://github.com/SylinaZhang/superset-3/tree/master/docs",
+ "git_url": "https://api.github.com/repos/SylinaZhang/superset-3/git/trees/c392f0e790ae8df54eb1b9527852c71d67631428",
+ "download_url": null,
+ "type": "dir",
+ "_links": {
+ "self": "https://api.github.com/repos/SylinaZhang/superset-3/contents/docs?ref=master",
+ "git": "https://api.github.com/repos/SylinaZhang/superset-3/git/trees/c392f0e790ae8df54eb1b9527852c71d67631428",
+ "html": "https://github.com/SylinaZhang/superset-3/tree/master/docs"
+ }
+ },
+ {
+ "name": "helm",
+ "path": "helm",
+ "sha": "30cb509191a10934fb310c5fcfe31c2c08ee5cc0",
+ "size": 0,
+ "url": "https://api.github.com/repos/SylinaZhang/superset-3/contents/helm?ref=master",
+ "html_url": "https://github.com/SylinaZhang/superset-3/tree/master/helm",
+ "git_url": "https://api.github.com/repos/SylinaZhang/superset-3/git/trees/30cb509191a10934fb310c5fcfe31c2c08ee5cc0",
+ "download_url": null,
+ "type": "dir",
+ "_links": {
+ "self": "https://api.github.com/repos/SylinaZhang/superset-3/contents/helm?ref=master",
+ "git": "https://api.github.com/repos/SylinaZhang/superset-3/git/trees/30cb509191a10934fb310c5fcfe31c2c08ee5cc0",
+ "html": "https://github.com/SylinaZhang/superset-3/tree/master/helm"
+ }
+ },
+ {
+ "name": "lintconf.yaml",
+ "path": "lintconf.yaml",
+ "sha": "5a7c114c6d18c090f2b28f5d591fb1332943c995",
+ "size": 1793,
+ "url": "https://api.github.com/repos/SylinaZhang/superset-3/contents/lintconf.yaml?ref=master",
+ "html_url": "https://github.com/SylinaZhang/superset-3/blob/master/lintconf.yaml",
+ "git_url": "https://api.github.com/repos/SylinaZhang/superset-3/git/blobs/5a7c114c6d18c090f2b28f5d591fb1332943c995",
+ "download_url": "https://raw.githubusercontent.com/SylinaZhang/superset-3/master/lintconf.yaml",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/SylinaZhang/superset-3/contents/lintconf.yaml?ref=master",
+ "git": "https://api.github.com/repos/SylinaZhang/superset-3/git/blobs/5a7c114c6d18c090f2b28f5d591fb1332943c995",
+ "html": "https://github.com/SylinaZhang/superset-3/blob/master/lintconf.yaml"
+ }
+ },
+ {
+ "name": "pytest.ini",
+ "path": "pytest.ini",
+ "sha": "fdb50114d8d185d218623dcfe7594a734423cff0",
+ "size": 861,
+ "url": "https://api.github.com/repos/SylinaZhang/superset-3/contents/pytest.ini?ref=master",
+ "html_url": "https://github.com/SylinaZhang/superset-3/blob/master/pytest.ini",
+ "git_url": "https://api.github.com/repos/SylinaZhang/superset-3/git/blobs/fdb50114d8d185d218623dcfe7594a734423cff0",
+ "download_url": "https://raw.githubusercontent.com/SylinaZhang/superset-3/master/pytest.ini",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/SylinaZhang/superset-3/contents/pytest.ini?ref=master",
+ "git": "https://api.github.com/repos/SylinaZhang/superset-3/git/blobs/fdb50114d8d185d218623dcfe7594a734423cff0",
+ "html": "https://github.com/SylinaZhang/superset-3/blob/master/pytest.ini"
+ }
+ },
+ {
+ "name": "requirements",
+ "path": "requirements",
+ "sha": "fc1e875f1117a33f3362997d815d867d63388833",
+ "size": 0,
+ "url": "https://api.github.com/repos/SylinaZhang/superset-3/contents/requirements?ref=master",
+ "html_url": "https://github.com/SylinaZhang/superset-3/tree/master/requirements",
+ "git_url": "https://api.github.com/repos/SylinaZhang/superset-3/git/trees/fc1e875f1117a33f3362997d815d867d63388833",
+ "download_url": null,
+ "type": "dir",
+ "_links": {
+ "self": "https://api.github.com/repos/SylinaZhang/superset-3/contents/requirements?ref=master",
+ "git": "https://api.github.com/repos/SylinaZhang/superset-3/git/trees/fc1e875f1117a33f3362997d815d867d63388833",
+ "html": "https://github.com/SylinaZhang/superset-3/tree/master/requirements"
+ }
+ },
+ {
+ "name": "scripts",
+ "path": "scripts",
+ "sha": "d3ab73567da9cc18f26c70d644bc7d495ad43473",
+ "size": 0,
+ "url": "https://api.github.com/repos/SylinaZhang/superset-3/contents/scripts?ref=master",
+ "html_url": "https://github.com/SylinaZhang/superset-3/tree/master/scripts",
+ "git_url": "https://api.github.com/repos/SylinaZhang/superset-3/git/trees/d3ab73567da9cc18f26c70d644bc7d495ad43473",
+ "download_url": null,
+ "type": "dir",
+ "_links": {
+ "self": "https://api.github.com/repos/SylinaZhang/superset-3/contents/scripts?ref=master",
+ "git": "https://api.github.com/repos/SylinaZhang/superset-3/git/trees/d3ab73567da9cc18f26c70d644bc7d495ad43473",
+ "html": "https://github.com/SylinaZhang/superset-3/tree/master/scripts"
+ }
+ },
+ {
+ "name": "setup.cfg",
+ "path": "setup.cfg",
+ "sha": "fc98b22708a4c3f5dfbc6bf61fb44b1242f535e0",
+ "size": 2241,
+ "url": "https://api.github.com/repos/SylinaZhang/superset-3/contents/setup.cfg?ref=master",
+ "html_url": "https://github.com/SylinaZhang/superset-3/blob/master/setup.cfg",
+ "git_url": "https://api.github.com/repos/SylinaZhang/superset-3/git/blobs/fc98b22708a4c3f5dfbc6bf61fb44b1242f535e0",
+ "download_url": "https://raw.githubusercontent.com/SylinaZhang/superset-3/master/setup.cfg",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/SylinaZhang/superset-3/contents/setup.cfg?ref=master",
+ "git": "https://api.github.com/repos/SylinaZhang/superset-3/git/blobs/fc98b22708a4c3f5dfbc6bf61fb44b1242f535e0",
+ "html": "https://github.com/SylinaZhang/superset-3/blob/master/setup.cfg"
+ }
+ },
+ {
+ "name": "setup.py",
+ "path": "setup.py",
+ "sha": "060ea19732b9bb84a8b4923c6f92b6f444ce191d",
+ "size": 7340,
+ "url": "https://api.github.com/repos/SylinaZhang/superset-3/contents/setup.py?ref=master",
+ "html_url": "https://github.com/SylinaZhang/superset-3/blob/master/setup.py",
+ "git_url": "https://api.github.com/repos/SylinaZhang/superset-3/git/blobs/060ea19732b9bb84a8b4923c6f92b6f444ce191d",
+ "download_url": "https://raw.githubusercontent.com/SylinaZhang/superset-3/master/setup.py",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/SylinaZhang/superset-3/contents/setup.py?ref=master",
+ "git": "https://api.github.com/repos/SylinaZhang/superset-3/git/blobs/060ea19732b9bb84a8b4923c6f92b6f444ce191d",
+ "html": "https://github.com/SylinaZhang/superset-3/blob/master/setup.py"
+ }
+ },
+ {
+ "name": "superset-embedded-sdk",
+ "path": "superset-embedded-sdk",
+ "sha": "666b3d88ad63800522299fe20e3690cc8803a01a",
+ "size": 0,
+ "url": "https://api.github.com/repos/SylinaZhang/superset-3/contents/superset-embedded-sdk?ref=master",
+ "html_url": "https://github.com/SylinaZhang/superset-3/tree/master/superset-embedded-sdk",
+ "git_url": "https://api.github.com/repos/SylinaZhang/superset-3/git/trees/666b3d88ad63800522299fe20e3690cc8803a01a",
+ "download_url": null,
+ "type": "dir",
+ "_links": {
+ "self": "https://api.github.com/repos/SylinaZhang/superset-3/contents/superset-embedded-sdk?ref=master",
+ "git": "https://api.github.com/repos/SylinaZhang/superset-3/git/trees/666b3d88ad63800522299fe20e3690cc8803a01a",
+ "html": "https://github.com/SylinaZhang/superset-3/tree/master/superset-embedded-sdk"
+ }
+ },
+ {
+ "name": "superset-frontend",
+ "path": "superset-frontend",
+ "sha": "6951cfef1aa1fe96d7a54e94ae5e0aa70b5beaed",
+ "size": 0,
+ "url": "https://api.github.com/repos/SylinaZhang/superset-3/contents/superset-frontend?ref=master",
+ "html_url": "https://github.com/SylinaZhang/superset-3/tree/master/superset-frontend",
+ "git_url": "https://api.github.com/repos/SylinaZhang/superset-3/git/trees/6951cfef1aa1fe96d7a54e94ae5e0aa70b5beaed",
+ "download_url": null,
+ "type": "dir",
+ "_links": {
+ "self": "https://api.github.com/repos/SylinaZhang/superset-3/contents/superset-frontend?ref=master",
+ "git": "https://api.github.com/repos/SylinaZhang/superset-3/git/trees/6951cfef1aa1fe96d7a54e94ae5e0aa70b5beaed",
+ "html": "https://github.com/SylinaZhang/superset-3/tree/master/superset-frontend"
+ }
+ },
+ {
+ "name": "superset-websocket",
+ "path": "superset-websocket",
+ "sha": "6abbeed2d3317ccc74b1df2659b11361cafa706e",
+ "size": 0,
+ "url": "https://api.github.com/repos/SylinaZhang/superset-3/contents/superset-websocket?ref=master",
+ "html_url": "https://github.com/SylinaZhang/superset-3/tree/master/superset-websocket",
+ "git_url": "https://api.github.com/repos/SylinaZhang/superset-3/git/trees/6abbeed2d3317ccc74b1df2659b11361cafa706e",
+ "download_url": null,
+ "type": "dir",
+ "_links": {
+ "self": "https://api.github.com/repos/SylinaZhang/superset-3/contents/superset-websocket?ref=master",
+ "git": "https://api.github.com/repos/SylinaZhang/superset-3/git/trees/6abbeed2d3317ccc74b1df2659b11361cafa706e",
+ "html": "https://github.com/SylinaZhang/superset-3/tree/master/superset-websocket"
+ }
+ },
+ {
+ "name": "superset",
+ "path": "superset",
+ "sha": "80dfebdf43901123b43ef065b11d9d02dff804a8",
+ "size": 0,
+ "url": "https://api.github.com/repos/SylinaZhang/superset-3/contents/superset?ref=master",
+ "html_url": "https://github.com/SylinaZhang/superset-3/tree/master/superset",
+ "git_url": "https://api.github.com/repos/SylinaZhang/superset-3/git/trees/80dfebdf43901123b43ef065b11d9d02dff804a8",
+ "download_url": null,
+ "type": "dir",
+ "_links": {
+ "self": "https://api.github.com/repos/SylinaZhang/superset-3/contents/superset?ref=master",
+ "git": "https://api.github.com/repos/SylinaZhang/superset-3/git/trees/80dfebdf43901123b43ef065b11d9d02dff804a8",
+ "html": "https://github.com/SylinaZhang/superset-3/tree/master/superset"
+ }
+ },
+ {
+ "name": "tests",
+ "path": "tests",
+ "sha": "3c0fd6da76ac85f3340fee8d8d76feba5c8371a9",
+ "size": 0,
+ "url": "https://api.github.com/repos/SylinaZhang/superset-3/contents/tests?ref=master",
+ "html_url": "https://github.com/SylinaZhang/superset-3/tree/master/tests",
+ "git_url": "https://api.github.com/repos/SylinaZhang/superset-3/git/trees/3c0fd6da76ac85f3340fee8d8d76feba5c8371a9",
+ "download_url": null,
+ "type": "dir",
+ "_links": {
+ "self": "https://api.github.com/repos/SylinaZhang/superset-3/contents/tests?ref=master",
+ "git": "https://api.github.com/repos/SylinaZhang/superset-3/git/trees/3c0fd6da76ac85f3340fee8d8d76feba5c8371a9",
+ "html": "https://github.com/SylinaZhang/superset-3/tree/master/tests"
+ }
+ },
+ {
+ "name": "tox.ini",
+ "path": "tox.ini",
+ "sha": "c63fa947df6f41b692c8989a08cf32201cf33f6a",
+ "size": 5406,
+ "url": "https://api.github.com/repos/SylinaZhang/superset-3/contents/tox.ini?ref=master",
+ "html_url": "https://github.com/SylinaZhang/superset-3/blob/master/tox.ini",
+ "git_url": "https://api.github.com/repos/SylinaZhang/superset-3/git/blobs/c63fa947df6f41b692c8989a08cf32201cf33f6a",
+ "download_url": "https://raw.githubusercontent.com/SylinaZhang/superset-3/master/tox.ini",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/SylinaZhang/superset-3/contents/tox.ini?ref=master",
+ "git": "https://api.github.com/repos/SylinaZhang/superset-3/git/blobs/c63fa947df6f41b692c8989a08cf32201cf33f6a",
+ "html": "https://github.com/SylinaZhang/superset-3/blob/master/tox.ini"
+ }
+ }
+]
diff --git a/uv/spec/fixtures/github/contents_directory_with_outside_reference_txt_file.json b/uv/spec/fixtures/github/contents_directory_with_outside_reference_txt_file.json
new file mode 100644
index 00000000000..cddc1613d9a
--- /dev/null
+++ b/uv/spec/fixtures/github/contents_directory_with_outside_reference_txt_file.json
@@ -0,0 +1,18 @@
+{
+ "name": "base.txt",
+ "path": "requirements/base.txt",
+ "sha": "1a971fdab49107704afab80fe08c52c656e292d2",
+ "size": 6494,
+ "url": "https://api.github.com/repos/SylinaZhang/superset-3/contents/requirements/base.txt?ref=master",
+ "html_url": "https://github.com/SylinaZhang/superset-3/blob/master/requirements/base.txt",
+ "git_url": "https://api.github.com/repos/SylinaZhang/superset-3/git/blobs/1a971fdab49107704afab80fe08c52c656e292d2",
+ "download_url": "https://raw.githubusercontent.com/SylinaZhang/superset-3/master/requirements/base.txt",
+ "type": "file",
+ "content": "IyBTSEExOmE5ZGRlMDQ4ZjFlZTFmMDA1ODYyNjRkNzI2ZDBlODlmMTZlNTYx\nODMKIwojIFRoaXMgZmlsZSBpcyBhdXRvZ2VuZXJhdGVkIGJ5IHBpcC1jb21w\naWxlLW11bHRpCiMgVG8gdXBkYXRlLCBydW46CiMKIyAgICBwaXAtY29tcGls\nZS1tdWx0aQojCi1lIGZpbGU6LgogICAgIyB2aWEgLXIgcmVxdWlyZW1lbnRz\nL2Jhc2UuaW4KYWxlbWJpYz09MS42LjUKICAgICMgdmlhIGZsYXNrLW1pZ3Jh\ndGUKYW1xcD09NS4xLjAKICAgICMgdmlhIGtvbWJ1CmFwaXNwZWNbeWFtbF09\nPTYuMy4wCiAgICAjIHZpYSBmbGFzay1hcHBidWlsZGVyCmFzeW5jLXRpbWVv\ndXQ9PTQuMC4yCiAgICAjIHZpYSByZWRpcwphdHRycz09MjMuMS4wCiAgICAj\nIHZpYSBqc29uc2NoZW1hCmJhYmVsPT0yLjkuMQogICAgIyB2aWEgZmxhc2st\nYmFiZWwKYmFja29mZj09MS4xMS4xCiAgICAjIHZpYSBhcGFjaGUtc3VwZXJz\nZXQKYmNyeXB0PT00LjAuMQogICAgIyB2aWEgcGFyYW1pa28KYmlsbGlhcmQ9\nPTMuNi40LjAKICAgICMgdmlhIGNlbGVyeQpicm90bGk9PTEuMC45CiAgICAj\nIHZpYSBmbGFzay1jb21wcmVzcwpjYWNoZWxpYj09MC42LjAKICAgICMgdmlh\nIGZsYXNrLWNhY2hpbmcKY2VsZXJ5PT01LjIuMgogICAgIyB2aWEgYXBhY2hl\nLXN1cGVyc2V0CmNmZmk9PTEuMTUuMQogICAgIyB2aWEKICAgICMgICBjcnlw\ndG9ncmFwaHkKICAgICMgICBweW5hY2wKY2xpY2s9PTguMS4zCiAgICAjIHZp\nYQogICAgIyAgIGFwYWNoZS1zdXBlcnNldAogICAgIyAgIGNlbGVyeQogICAg\nIyAgIGNsaWNrLWRpZHlvdW1lYW4KICAgICMgICBjbGljay1vcHRpb24tZ3Jv\ndXAKICAgICMgICBjbGljay1wbHVnaW5zCiAgICAjICAgY2xpY2stcmVwbAog\nICAgIyAgIGZsYXNrCiAgICAjICAgZmxhc2stYXBwYnVpbGRlcgpjbGljay1k\naWR5b3VtZWFuPT0wLjMuMAogICAgIyB2aWEgY2VsZXJ5CmNsaWNrLW9wdGlv\nbi1ncm91cD09MC41LjUKICAgICMgdmlhIGFwYWNoZS1zdXBlcnNldApjbGlj\nay1wbHVnaW5zPT0xLjEuMQogICAgIyB2aWEgY2VsZXJ5CmNsaWNrLXJlcGw9\nPTAuMi4wCiAgICAjIHZpYSBjZWxlcnkKY29sb3JhbWE9PTAuNC42CiAgICAj\nIHZpYQogICAgIyAgIGFwYWNoZS1zdXBlcnNldAogICAgIyAgIGZsYXNrLWFw\ncGJ1aWxkZXIKY29udmVydGRhdGU9PTIuNC4wCiAgICAjIHZpYSBob2xpZGF5\ncwpjcm9uLWRlc2NyaXB0b3I9PTEuMi4yNAogICAgIyB2aWEgYXBhY2hlLXN1\ncGVyc2V0CmNyb25pdGVyPT0xLjAuMTUKICAgICMgdmlhIGFwYWNoZS1zdXBl\ncnNldApjcnlwdG9ncmFwaHk9PTM5LjAuMQogICAgIyB2aWEKICAgICMgICBh\ncGFjaGUtc3VwZXJzZXQKICAgICMgICBwYXJhbWlrbwpkZXByZWNhdGVkPT0x\nLjIuMTMKICAgICMgdmlhIGxpbWl0cwpkZXByZWNhdGlvbj09Mi4xLjAKICAg\nICMgdmlhIGFwYWNoZS1zdXBlcnNldApkbnNweXRob249PTIuMS4wCiAgICAj\nIHZpYSBlbWFpbC12YWxpZGF0b3IKZW1haWwtdmFsaWRhdG9yPT0xLjEuMwog\nICAgIyB2aWEgZmxhc2stYXBwYnVpbGRlcgpmbGFzaz09Mi4yLjUKICAgICMg\ndmlhCiAgICAjICAgYXBhY2hlLXN1cGVyc2V0CiAgICAjICAgZmxhc2stYXBw\nYnVpbGRlcgogICAgIyAgIGZsYXNrLWJhYmVsCiAgICAjICAgZmxhc2stY2Fj\naGluZwogICAgIyAgIGZsYXNrLWNvbXByZXNzCiAgICAjICAgZmxhc2stand0\nLWV4dGVuZGVkCiAgICAjICAgZmxhc2stbGltaXRlcgogICAgIyAgIGZsYXNr\nLWxvZ2luCiAgICAjICAgZmxhc2stbWlncmF0ZQogICAgIyAgIGZsYXNrLXNx\nbGFsY2hlbXkKICAgICMgICBmbGFzay13dGYKZmxhc2stYXBwYnVpbGRlcj09\nNC4zLjYKICAgICMgdmlhIGFwYWNoZS1zdXBlcnNldApmbGFzay1iYWJlbD09\nMS4wLjAKICAgICMgdmlhIGZsYXNrLWFwcGJ1aWxkZXIKZmxhc2stY2FjaGlu\nZz09MS4xMS4xCiAgICAjIHZpYSBhcGFjaGUtc3VwZXJzZXQKZmxhc2stY29t\ncHJlc3M9PTEuMTMKICAgICMgdmlhIGFwYWNoZS1zdXBlcnNldApmbGFzay1q\nd3QtZXh0ZW5kZWQ9PTQuMy4xCiAgICAjIHZpYSBmbGFzay1hcHBidWlsZGVy\nCmZsYXNrLWxpbWl0ZXI9PTMuMy4xCiAgICAjIHZpYSBmbGFzay1hcHBidWls\nZGVyCmZsYXNrLWxvZ2luPT0wLjYuMAogICAgIyB2aWEKICAgICMgICBhcGFj\naGUtc3VwZXJzZXQKICAgICMgICBmbGFzay1hcHBidWlsZGVyCmZsYXNrLW1p\nZ3JhdGU9PTMuMS4wCiAgICAjIHZpYSBhcGFjaGUtc3VwZXJzZXQKZmxhc2st\nc3FsYWxjaGVteT09Mi41LjEKICAgICMgdmlhCiAgICAjICAgZmxhc2stYXBw\nYnVpbGRlcgogICAgIyAgIGZsYXNrLW1pZ3JhdGUKZmxhc2stdGFsaXNtYW49\nPTEuMC4wCiAgICAjIHZpYSBhcGFjaGUtc3VwZXJzZXQKZmxhc2std3RmPT0x\nLjEuMQogICAgIyB2aWEKICAgICMgICBhcGFjaGUtc3VwZXJzZXQKICAgICMg\nICBmbGFzay1hcHBidWlsZGVyCmZ1bmMtdGltZW91dD09NC4zLjUKICAgICMg\ndmlhIGFwYWNoZS1zdXBlcnNldApnZW9ncmFwaGljbGliPT0xLjUyCiAgICAj\nIHZpYSBnZW9weQpnZW9weT09Mi4yLjAKICAgICMgdmlhIGFwYWNoZS1zdXBl\ncnNldApndW5pY29ybj09MjAuMS4wCiAgICAjIHZpYSBhcGFjaGUtc3VwZXJz\nZXQKaGFzaGlkcz09MS4zLjEKICAgICMgdmlhIGFwYWNoZS1zdXBlcnNldApo\naWpyaS1jb252ZXJ0ZXI9PTIuMy4xCiAgICAjIHZpYSBob2xpZGF5cwpob2xp\nZGF5cz09MC4yMwogICAgIyB2aWEgYXBhY2hlLXN1cGVyc2V0Cmh1bWFuaXpl\nPT0zLjExLjAKICAgICMgdmlhIGFwYWNoZS1zdXBlcnNldAppZG5hPT0zLjIK\nICAgICMgdmlhIGVtYWlsLXZhbGlkYXRvcgppbXBvcnRsaWItbWV0YWRhdGE9\nPTYuNi4wCiAgICAjIHZpYSBhcGFjaGUtc3VwZXJzZXQKaW1wb3J0bGliLXJl\nc291cmNlcz09NS4xMi4wCiAgICAjIHZpYSBsaW1pdHMKaXNvZGF0ZT09MC42\nLjAKICAgICMgdmlhIGFwYWNoZS1zdXBlcnNldAppdHNkYW5nZXJvdXM9PTIu\nMS4yCiAgICAjIHZpYQogICAgIyAgIGZsYXNrCiAgICAjICAgZmxhc2std3Rm\nCmppbmphMj09My4xLjIKICAgICMgdmlhCiAgICAjICAgZmxhc2sKICAgICMg\nICBmbGFzay1iYWJlbApqc29uc2NoZW1hPT00LjE3LjMKICAgICMgdmlhIGZs\nYXNrLWFwcGJ1aWxkZXIKa29tYnU9PTUuMi40CiAgICAjIHZpYSBjZWxlcnkK\na29yZWFuLWx1bmFyLWNhbGVuZGFyPT0wLjMuMQogICAgIyB2aWEgaG9saWRh\neXMKbGltaXRzPT0zLjQuMAogICAgIyB2aWEgZmxhc2stbGltaXRlcgptYWtv\nPT0xLjIuNAogICAgIyB2aWEKICAgICMgICBhbGVtYmljCiAgICAjICAgYXBh\nY2hlLXN1cGVyc2V0Cm1hcmtkb3duPT0zLjMuNAogICAgIyB2aWEgYXBhY2hl\nLXN1cGVyc2V0Cm1hcmtkb3duLWl0LXB5PT0yLjIuMAogICAgIyB2aWEgcmlj\naAptYXJrdXBzYWZlPT0yLjEuMQogICAgIyB2aWEKICAgICMgICBqaW5qYTIK\nICAgICMgICBtYWtvCiAgICAjICAgd2Vya3pldWcKICAgICMgICB3dGZvcm1z\nCm1hcnNobWFsbG93PT0zLjE5LjAKICAgICMgdmlhCiAgICAjICAgZmxhc2st\nYXBwYnVpbGRlcgogICAgIyAgIG1hcnNobWFsbG93LXNxbGFsY2hlbXkKbWFy\nc2htYWxsb3ctc3FsYWxjaGVteT09MC4yMy4xCiAgICAjIHZpYSBmbGFzay1h\ncHBidWlsZGVyCm1kdXJsPT0wLjEuMgogICAgIyB2aWEgbWFya2Rvd24taXQt\ncHkKbXNncGFjaz09MS4wLjIKICAgICMgdmlhIGFwYWNoZS1zdXBlcnNldApu\naDM9PTAuMi4xMQogICAgIyB2aWEgYXBhY2hlLXN1cGVyc2V0Cm51bXB5PT0x\nLjIzLjUKICAgICMgdmlhCiAgICAjICAgYXBhY2hlLXN1cGVyc2V0CiAgICAj\nICAgcGFuZGFzCiAgICAjICAgcHlhcnJvdwpvcmRlcmVkLXNldD09NC4xLjAK\nICAgICMgdmlhIGZsYXNrLWxpbWl0ZXIKcGFja2FnaW5nPT0yMy4xCiAgICAj\nIHZpYQogICAgIyAgIGFwYWNoZS1zdXBlcnNldAogICAgIyAgIGFwaXNwZWMK\nICAgICMgICBkZXByZWNhdGlvbgogICAgIyAgIGxpbWl0cwogICAgIyAgIG1h\ncnNobWFsbG93CnBhbmRhcz09MS41LjMKICAgICMgdmlhIGFwYWNoZS1zdXBl\ncnNldApwYXJhbWlrbz09Mi4xMS4wCiAgICAjIHZpYSBzc2h0dW5uZWwKcGFy\nc2VkYXRldGltZT09Mi42CiAgICAjIHZpYSBhcGFjaGUtc3VwZXJzZXQKcGdz\nYW5pdHk9PTAuMi45CiAgICAjIHZpYSBhcGFjaGUtc3VwZXJzZXQKcG9seWxp\nbmU9PTIuMC4wCiAgICAjIHZpYSBhcGFjaGUtc3VwZXJzZXQKcHJpc29uPT0w\nLjIuMQogICAgIyB2aWEgZmxhc2stYXBwYnVpbGRlcgpwcm9tcHQtdG9vbGtp\ndD09My4wLjM4CiAgICAjIHZpYSBjbGljay1yZXBsCnB5YXJyb3c9PTEyLjAu\nMAogICAgIyB2aWEgYXBhY2hlLXN1cGVyc2V0CnB5Y3BhcnNlcj09Mi4yMAog\nICAgIyB2aWEgY2ZmaQpweWdtZW50cz09Mi4xNS4wCiAgICAjIHZpYSByaWNo\nCnB5and0PT0yLjQuMAogICAgIyB2aWEKICAgICMgICBhcGFjaGUtc3VwZXJz\nZXQKICAgICMgICBmbGFzay1hcHBidWlsZGVyCiAgICAjICAgZmxhc2stand0\nLWV4dGVuZGVkCnB5bWVldXM9PTAuNS4xMgogICAgIyB2aWEgY29udmVydGRh\ndGUKcHluYWNsPT0xLjUuMAogICAgIyB2aWEgcGFyYW1pa28KcHlwYXJzaW5n\nPT0zLjAuNgogICAgIyB2aWEgYXBhY2hlLXN1cGVyc2V0CnB5cnNpc3RlbnQ9\nPTAuMTkuMwogICAgIyB2aWEganNvbnNjaGVtYQpweXRob24tZGF0ZXV0aWw9\nPTIuOC4yCiAgICAjIHZpYQogICAgIyAgIGFsZW1iaWMKICAgICMgICBhcGFj\naGUtc3VwZXJzZXQKICAgICMgICBjcm9uaXRlcgogICAgIyAgIGZsYXNrLWFw\ncGJ1aWxkZXIKICAgICMgICBob2xpZGF5cwogICAgIyAgIHBhbmRhcwpweXRo\nb24tZG90ZW52PT0wLjE5LjAKICAgICMgdmlhIGFwYWNoZS1zdXBlcnNldApw\neXRob24tZWRpdG9yPT0xLjAuNAogICAgIyB2aWEgYWxlbWJpYwpweXRob24t\nZ2VvaGFzaD09MC44LjUKICAgICMgdmlhIGFwYWNoZS1zdXBlcnNldApweXR6\nPT0yMDIxLjMKICAgICMgdmlhCiAgICAjICAgYmFiZWwKICAgICMgICBjZWxl\ncnkKICAgICMgICBmbGFzay1iYWJlbAogICAgIyAgIHBhbmRhcwpweXlhbWw9\nPTYuMC4xCiAgICAjIHZpYQogICAgIyAgIGFwYWNoZS1zdXBlcnNldAogICAg\nIyAgIGFwaXNwZWMKcmVkaXM9PTQuNS40CiAgICAjIHZpYSBhcGFjaGUtc3Vw\nZXJzZXQKcmljaD09MTMuMy40CiAgICAjIHZpYSBmbGFzay1saW1pdGVyCnNl\nbGVuaXVtPT0zLjE0MS4wCiAgICAjIHZpYSBhcGFjaGUtc3VwZXJzZXQKc2hv\ncnRpZD09MC4xLjIKICAgICMgdmlhIGFwYWNoZS1zdXBlcnNldApzaW1wbGVq\nc29uPT0zLjE3LjMKICAgICMgdmlhIGFwYWNoZS1zdXBlcnNldApzaXg9PTEu\nMTYuMAogICAgIyB2aWEKICAgICMgICBjbGljay1yZXBsCiAgICAjICAgaXNv\nZGF0ZQogICAgIyAgIHBhcmFtaWtvCiAgICAjICAgcHJpc29uCiAgICAjICAg\ncHl0aG9uLWRhdGV1dGlsCiAgICAjICAgd3Rmb3Jtcy1qc29uCnNsYWNrLXNk\naz09My4yMS4zCiAgICAjIHZpYSBhcGFjaGUtc3VwZXJzZXQKc3FsYWxjaGVt\neT09MS40LjM2CiAgICAjIHZpYQogICAgIyAgIGFsZW1iaWMKICAgICMgICBh\ncGFjaGUtc3VwZXJzZXQKICAgICMgICBmbGFzay1hcHBidWlsZGVyCiAgICAj\nICAgZmxhc2stc3FsYWxjaGVteQogICAgIyAgIG1hcnNobWFsbG93LXNxbGFs\nY2hlbXkKICAgICMgICBzcWxhbGNoZW15LXV0aWxzCnNxbGFsY2hlbXktdXRp\nbHM9PTAuMzguMwogICAgIyB2aWEKICAgICMgICBhcGFjaGUtc3VwZXJzZXQK\nICAgICMgICBmbGFzay1hcHBidWlsZGVyCnNxbHBhcnNlPT0wLjQuNAogICAg\nIyB2aWEgYXBhY2hlLXN1cGVyc2V0CnNzaHR1bm5lbD09MC40LjAKICAgICMg\ndmlhIGFwYWNoZS1zdXBlcnNldAp0YWJ1bGF0ZT09MC44LjkKICAgICMgdmlh\nIGFwYWNoZS1zdXBlcnNldAp0eXBpbmctZXh0ZW5zaW9ucz09NC40LjAKICAg\nICMgdmlhCiAgICAjICAgYXBhY2hlLXN1cGVyc2V0CiAgICAjICAgZmxhc2st\nbGltaXRlcgogICAgIyAgIGxpbWl0cwp1cmxsaWIzPT0xLjI2LjYKICAgICMg\ndmlhIHNlbGVuaXVtCnZpbmU9PTUuMC4wCiAgICAjIHZpYQogICAgIyAgIGFt\ncXAKICAgICMgICBjZWxlcnkKICAgICMgICBrb21idQp3Y3dpZHRoPT0wLjIu\nNQogICAgIyB2aWEgcHJvbXB0LXRvb2xraXQKd2Vya3pldWc9PTIuMy4zCiAg\nICAjIHZpYQogICAgIyAgIGFwYWNoZS1zdXBlcnNldAogICAgIyAgIGZsYXNr\nCiAgICAjICAgZmxhc2stand0LWV4dGVuZGVkCiAgICAjICAgZmxhc2stbG9n\naW4Kd3JhcHQ9PTEuMTIuMQogICAgIyB2aWEgZGVwcmVjYXRlZAp3dGZvcm1z\nPT0yLjMuMwogICAgIyB2aWEKICAgICMgICBhcGFjaGUtc3VwZXJzZXQKICAg\nICMgICBmbGFzay1hcHBidWlsZGVyCiAgICAjICAgZmxhc2std3RmCiAgICAj\nICAgd3Rmb3Jtcy1qc29uCnd0Zm9ybXMtanNvbj09MC4zLjUKICAgICMgdmlh\nIGFwYWNoZS1zdXBlcnNldAp4bHN4d3JpdGVyPT0zLjAuNwogICAgIyB2aWEg\nYXBhY2hlLXN1cGVyc2V0CnppcHA9PTMuMTUuMAogICAgIyB2aWEgaW1wb3J0\nbGliLW1ldGFkYXRhCgojIFRoZSBmb2xsb3dpbmcgcGFja2FnZXMgYXJlIGNv\nbnNpZGVyZWQgdG8gYmUgdW5zYWZlIGluIGEgcmVxdWlyZW1lbnRzIGZpbGU6\nCiMgc2V0dXB0b29scwo=\n",
+ "encoding": "base64",
+ "_links": {
+ "self": "https://api.github.com/repos/SylinaZhang/superset-3/contents/requirements/base.txt?ref=master",
+ "git": "https://api.github.com/repos/SylinaZhang/superset-3/git/blobs/1a971fdab49107704afab80fe08c52c656e292d2",
+ "html": "https://github.com/SylinaZhang/superset-3/blob/master/requirements/base.txt"
+ }
+}
diff --git a/uv/spec/fixtures/github/contents_image.json b/uv/spec/fixtures/github/contents_image.json
new file mode 100644
index 00000000000..f5dd2633be1
--- /dev/null
+++ b/uv/spec/fixtures/github/contents_image.json
@@ -0,0 +1,18 @@
+{
+ "name": "affine.png",
+ "path": "images/affine.png",
+ "sha": "2c9601bd6e7a46bedb4303f95fca181c961ee406",
+ "size": 2975,
+ "url": "https://api.github.com/repos/ImageMagick/ImageMagick/contents/images/affine.png?ref=master",
+ "html_url": "https://github.com/ImageMagick/ImageMagick/blob/master/images/affine.png",
+ "git_url": "https://api.github.com/repos/ImageMagick/ImageMagick/git/blobs/2c9601bd6e7a46bedb4303f95fca181c961ee406",
+ "download_url": "https://raw.githubusercontent.com/ImageMagick/ImageMagick/master/images/affine.png",
+ "type": "file",
+ "content": "iVBORw0KGgoAAAANSUhEUgAAATAAAABVCAIAAABB1y/5AAAALHRFWHRDcmVh\ndGlvbiBUaW1lAFNhdCAyMCBEZWMgMjAwOCAxNzowMDo0NiAtMDYwMBxDBZoA\nAAAHdElNRQfYDBQXAgwK24J3AAAACXBIWXMAAA7DAAAOwwHHb6hkAAAABGdB\nTUEAALGPC/xhBQAACvZJREFUeNrtnet127oShem7TgNJCVEJVyXEJdgl2CVY\nJTglxCUoJSQlyCUoJdgl6OzLvYLDywc4GAAk5bO/H1q0IgLgDgYYPDi4uVwu\njRBiG/xn7QIIIf5BBinEhpBBCrEhZJBCbAgZpBAbQgYpxIaQQQqxIWSQIo3f\nv3//+PFj7VJsHUgEoRw3yiBFAu/v7/f392uX4jqAUJAr9S4ZpEjg27dvX758\nubu7W7sgKwDren19NdoYJIJQkCs1lxttnRNGfv36hVb/fD5/+vRp7bIsDUwL\nLujDwwNEwMXz8/OsCDDd3W53PB6/fv2akNNFCANvb29o8lER1y7ICtCowp9P\nLZYbIRdEg3T2vGSQwgT7hKS69WGAUX3//j38eTqdjFLgN/hlUiumMaSYB94X\nfDZ0C/9CZ/V3C2wyfINrCALfdfZeyAXRIJ19duevtZ9XXAEvLy/4xAgq9UZU\n5VBx/9tStmBcXYCFwKXkYgyqPmygYBavr69Na1rhG17je8vkFkSDQUJAa6nW\ndgfEFYAaj4qVetf5fEaV5TWct3BdCqRJTxLVGNUdf7LSl80FWSBNuKndL2lp\nxhTwSwho/LFcVjED5xUdSx3oFsJduHYsysVBl4j02YOh0qPjwufPnz/XFqwP\nCtn1FOLIIMUMsCX6hI57D4cDbkd1RN9V3FRQJBghKvqXlqYd3fnKWRUUCQWj\n2z+LDFLE4OyFr5bTVXt8fNztdre3t8XLRiM0juXcTM1jJc1vQUDIaPERZJAi\nBquRzyBhMOgVL+06HszG6LM5Slh8rqj3FE3bMIVveN2dd50FAhonZjXLKmJw\nhOYwSPSK6CE5y4IeLOxHx0XodbkZDebqLh6c4dH2omAusHZ0ht2d4rxO0oQ/\ntnTm6iFFDNRsdAWpy49cigiV772FbhunXvDJ2pk50zNavOK5oFnpdm645lZV\newooCX5vekum7Byx+Ei8vb01KfP7XZ6fn9EpnU4nfKJCn8/nS7sQwn+FcdKb\nzQSGMdzFVjwXrtlwww0SRLIhCztcxZ3d3yODFJNwXrS7aywJVD4Y5LDu0s5Z\nNTP34r21TP1TqVwIngVSuC2c65mzt8tlFZNwAJnkm3WBn4YBWPd2+GyvLfQz\n4UkaFwMiWQzd6eK5EDwLejn3skqYE47/TAYpJuHshdsgh3CnG8d4qJqwE8d2\nvI3kkgplnA0joPchxST7/R4VumwNQYLoatBroWrWW65YJpdUbm5uUBi4vrHf\nyCDFFLvdDp8YBK5dkA+CRU+5rGISdC//wvet6tFbzxxFBinGcexHEXGGm36G\nyCDFOGzL1UMWhGLGO8kqBok2gHuXNpKOENdCmkEagxG8vLz4glLWSIfhJ7KF\nSiMpasPCGAWRy1qcwi7r4XDgG2izv+y+opaDL53eA6PAKDYKn1mYGkItwPC/\n3yiIXNYeSXFZRynpsnJzrXFJB+UushSbmg4KeXt7O9zCy2JXev0nR6jaJRlV\nY2FBPgbwKdiEwWt7fHys6P4Yd+LZw0tymSV/92BSOsfjEabLV2xG914yrGhm\nkcoKVY9ZNSyCcO+leyPrR8Idl7WHRVJTD0nX0ei9oEku4rAlpXN3d4fnjLxs\nxvdfavcJSULVY1YNiyDsBDY7El4S9I1dMXHtCxFkkdRkkLQNY65r+auzhEiB\n9UgSanXigrBZWb1xWZ2cuKw9LJKaIgYgb/a2Ae6mR0EZwIeBHvhOKkiyXqbT\nDcKLBgl/JqVjAQOnIrv+k4SKa+UWp4id1BNkgXCpPeoFgM2My5qMxfdt/n8s\nx7dOL38ipdOfhvRQIcmlxu186ZMuFr/MHII20VFT5HkZ5HOW+Ptsw5K7tSoi\nThMdscQFcY8hlwmX2qVqANj8uKy9pHLHkMMWgiEMeB0imkD01LAlSIdOKd+U\n4Ze+mBEWQsNWPOUpoXK0WkCcSoIsHy61dgDYJfEEuQqeJETnolbjioPEukWX\nppvmKscPst4UT9at1abESX3kYbjU2hsM4MmzveMU6Noa+PFsnQsOemYEPt7L\nBjW0+rWj+i2MW6vrFWeZcKldqgaALRKX1U5WGEiInj/v0p0ImYrqtwDcNzv7\nM3dsbJ9WGxHHwej8ViUYALZp2y+YpTuy81TiTXZcVjvzPSSb5KFfzpnf0GD7\ndm/2Klm9AWR4hHo9zJRQbq1qi1NPkKm2A9/j2dGJMWs8Uf40L3rFsDU3zMwX\nzKhIXNYELLNDIQT1pd2mwB0ex+MRBeXsU5gSHIVnfY7OT3ZDgwE8fGQPRCSd\n7vTX1CwWbqy9WacrlFErtziZaswKkrNThycHj36PTxSboehQpzkF7QbpdIMy\nQituqSmbEVLrztz2/rRTbKcOnqc7F4eawcU0lAxtD64tcYRGF1K5EoDb8a9o\n0hgKxZEOvoSvwvED0sH18IWGIg52klB2rdziuNWoKsjUABJfdid78gvAEQQX\nbCEvHpOVvmxG/P+ihr9a8L9ZQ7f/YbFsBoftNkuhTepezzYzkXYOMPjP7CKb\n+5j7UmFz7ULZtXKL41ZjVhAuzPg6lki4VDQxIeJwKYdlNABs8Ywy47JebJKW\n31w+JdloOVAnQpVCqza72DqVjqUAm91c7hbHrYZFkEqby9HJs07j0XxbtLeW\nkZ1iLitTyXnNF37X6BC/+TM4Dn6dIx0LwZmpjUMotzhuNZYUpAedSbqXVZdw\nFsuoLNZlD56UYhnjDeFdw+nBMADgQIgzH450LAVo6k2L5QnlFsetxsKCdEGz\n0h1b1ivAYhmVJ6nPRSO9+st+qcRngCuxZaGMgtRwWcO4Du531TctF8soCYuk\nCpQsxkEvut/vWbNLpcl3Mowvu1xFRkkcDgf4z6fTKeI96cBWEaPsRm2YxzLH\nbCyWURI60lyIK0MGKcahWzUb+l7YoZjx2T4ZpIhx1e8Wbg25rCILtOXqIXvk\ntFCWs/FkkGISHj/svt0XCWqzGUXi3NrLObtuLIMUk7A5d8f4+NayQDlrZ8TX\nLDPNnjLO9pBa9hCThFO4fVvPFni9ZpmMGEsxMxHj+fDqIcUkOROtvXey67FY\nRplYplgb9ZAiAvfKprqs8B4ZMaBpnT3Ad6mLF2+xjIrAKGfzDcfa+/vEpmEI\nOceNT09PvVdDK7FYRpe5CAxxGHNw9mdyWUUM1CF0QQ6v9cMMIItgD1AmgxQx\nWIdS5/o1gOzRi68bQQYpYqCuO04N60aFrspiGWXCAD+WhkMGKWbguQBJOwQW\n67Wuonvk0cvGhRMZpJjh4eHBGEU60B3XhSV7Bke9v7/HJ77ERX7ZhhnVCP2a\nCcqAwhhfB5NBihm6p8oZCRFMeBRC8+fIIJ69w+6iyLb1YUa4eHp6Cl06rHH1\nhRCeGmqMdK51SDEPqjj6HHugIBheMIneeTs87jIE/89kmFHx0K9N25rwxMum\n7YeRJhI3HunDqEj2h1UID2ECBomuxn7iIKrvp5bul7Ccz58/86hMy05rX0aH\nw4ExphkwmodqrgU8czyp3SDlsgoTqN+hl7DQO4YE9zK+OL9HHS01tBuedxJm\nelY/vQ9y0YW236IeUljhNEzqsbzhXs7W8lQsHkdbaXTHs4xgk+gekdeKNulQ\nTAYprKCW73Y7VC/3gXwwEu77qbdW8d7C6/1+D391rUkdNDowyOQCLLMJUHwM\neE7GZkPOXjYTkZUnNTgOAlEPKdI4HA7o4nyO6wJsJCIr+kYUwBHSVgYpxIbQ\nLKsQG0IGKcSGkEEKsSFkkEJsCBmkEBtCBinEhvgb/dDUOgeJAaQAAAAASUVO\nRK5CYII=\n",
+ "encoding": "base64",
+ "_links": {
+ "self": "https://api.github.com/repos/ImageMagick/ImageMagick/contents/images/affine.png?ref=master",
+ "git": "https://api.github.com/repos/ImageMagick/ImageMagick/git/blobs/2c9601bd6e7a46bedb4303f95fca181c961ee406",
+ "html": "https://github.com/ImageMagick/ImageMagick/blob/master/images/affine.png"
+ }
+}
diff --git a/uv/spec/fixtures/github/contents_pyproject_with_path.json b/uv/spec/fixtures/github/contents_pyproject_with_path.json
new file mode 100644
index 00000000000..54cbee0edb3
--- /dev/null
+++ b/uv/spec/fixtures/github/contents_pyproject_with_path.json
@@ -0,0 +1,18 @@
+{
+ "name": "pyproject.toml",
+ "path": "pyproject.toml",
+ "sha": "1ebadf060e206ca2414c1facbdeb7f8253f2d597",
+ "size": 1798,
+ "url": "https://api.github.com/repos/sdispater/poetry/contents/pyproject.toml?ref=master",
+ "html_url": "https://github.com/sdispater/poetry/blob/master/pyproject.toml",
+ "git_url": "https://api.github.com/repos/sdispater/poetry/git/blobs/1ebadf060e206ca2414c1facbdeb7f8253f2d597",
+ "download_url": "https://raw.githubusercontent.com/sdispater/poetry/master/pyproject.toml",
+ "type": "file",
+ "content": "W3Rvb2wucG9ldHJ5XQpuYW1lID0gIlB5dGhvblByb2plY3RzIgp2ZXJzaW9u\nID0gIjIuMC4wIgpob21lcGFnZSA9ICJodHRwczovL2dpdGh1Yi5jb20vcm9n\naHUvcHkzX3Byb2plY3RzIgpsaWNlbnNlID0gIk1JVCIKcmVhZG1lID0gIlJF\nQURNRS5tZCIKYXV0aG9ycyA9IFsiRGVwZW5kYWJvdCA8c3VwcG9ydEBkZXBl\nbmRhYm90LmNvbT4iXQpkZXNjcmlwdGlvbiA9ICJWYXJpb3VzIHNtYWxsIHB5\ndGhvbiBwcm9qZWN0cy4iCgpbdG9vbC5wb2V0cnkuZGVwZW5kZW5jaWVzXQpw\neXRob24gPSAifjMuNiIKbnVtcHkgPSAiMS4xNi4xIgpteV9kZXAgPSB7cGF0\naCA9ICJwYXRoX2RlcC8ifQo=\n",
+ "encoding": "base64",
+ "_links": {
+ "self": "https://api.github.com/repos/sdispater/poetry/contents/pyproject.toml?ref=master",
+ "git": "https://api.github.com/repos/sdispater/poetry/git/blobs/1ebadf060e206ca2414c1facbdeb7f8253f2d597",
+ "html": "https://github.com/sdispater/poetry/blob/master/pyproject.toml"
+ }
+}
diff --git a/uv/spec/fixtures/github/contents_python.json b/uv/spec/fixtures/github/contents_python.json
new file mode 100644
index 00000000000..10d6505a7a9
--- /dev/null
+++ b/uv/spec/fixtures/github/contents_python.json
@@ -0,0 +1,434 @@
+[
+ {
+ "name": ".codeclimate.yml",
+ "path": ".codeclimate.yml",
+ "sha": "6393602fac96cfe31d64f89476014124b4a13b85",
+ "size": 416,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.codeclimate.yml?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.codeclimate.yml",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/6393602fac96cfe31d64f89476014124b4a13b85",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/.codeclimate.yml",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.codeclimate.yml?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/6393602fac96cfe31d64f89476014124b4a13b85",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.codeclimate.yml"
+ }
+ },
+ {
+ "name": ".coveragerc",
+ "path": ".coveragerc",
+ "sha": "be7fdc86067d0924f3e1e92c1a3ed92d9486fcbb",
+ "size": 646,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.coveragerc?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.coveragerc",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/be7fdc86067d0924f3e1e92c1a3ed92d9486fcbb",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/.coveragerc",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.coveragerc?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/be7fdc86067d0924f3e1e92c1a3ed92d9486fcbb",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.coveragerc"
+ }
+ },
+ {
+ "name": ".csslintrc",
+ "path": ".csslintrc",
+ "sha": "aacba956e5bbede1c195ce554fcad3e200b24ff8",
+ "size": 107,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.csslintrc?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.csslintrc",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/aacba956e5bbede1c195ce554fcad3e200b24ff8",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/.csslintrc",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.csslintrc?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/aacba956e5bbede1c195ce554fcad3e200b24ff8",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.csslintrc"
+ }
+ },
+ {
+ "name": ".env.example",
+ "path": ".env.example",
+ "sha": "d9f599b33ecd834ea88979dcc3daf4fcafacf4e7",
+ "size": 2617,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.env.example?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.env.example",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/d9f599b33ecd834ea88979dcc3daf4fcafacf4e7",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/.env.example",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.env.example?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/d9f599b33ecd834ea88979dcc3daf4fcafacf4e7",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.env.example"
+ }
+ },
+ {
+ "name": ".eslintignore",
+ "path": ".eslintignore",
+ "sha": "96212a3593bac8c93f624b77185a8d11018efd96",
+ "size": 16,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.eslintignore?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.eslintignore",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/96212a3593bac8c93f624b77185a8d11018efd96",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/.eslintignore",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.eslintignore?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/96212a3593bac8c93f624b77185a8d11018efd96",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.eslintignore"
+ }
+ },
+ {
+ "name": ".eslintrc.yml",
+ "path": ".eslintrc.yml",
+ "sha": "a6a0ce9c44238e06ff55ca335a66a4e16810da38",
+ "size": 6056,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.eslintrc.yml?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.eslintrc.yml",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/a6a0ce9c44238e06ff55ca335a66a4e16810da38",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/.eslintrc.yml",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.eslintrc.yml?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/a6a0ce9c44238e06ff55ca335a66a4e16810da38",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.eslintrc.yml"
+ }
+ },
+ {
+ "name": ".gitignore",
+ "path": ".gitignore",
+ "sha": "93923ac3a463bd17d0aefca2de9d2810f243d747",
+ "size": 1073,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.gitignore?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.gitignore",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/93923ac3a463bd17d0aefca2de9d2810f243d747",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/.gitignore",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.gitignore?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/93923ac3a463bd17d0aefca2de9d2810f243d747",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.gitignore"
+ }
+ },
+ {
+ "name": "LICENSE.md",
+ "path": "LICENSE.md",
+ "sha": "8dada3edaf50dbc082c9a125058f25def75e625a",
+ "size": 11357,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/LICENSE.md?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/LICENSE.md",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/8dada3edaf50dbc082c9a125058f25def75e625a",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/LICENSE.md",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/LICENSE.md?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/8dada3edaf50dbc082c9a125058f25def75e625a",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/LICENSE.md"
+ }
+ },
+ {
+ "name": "Procfile",
+ "path": "Procfile",
+ "sha": "72e4ef1be7c64eb0f874344bc8a6cf859bd39e00",
+ "size": 26,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/Procfile?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/Procfile",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/72e4ef1be7c64eb0f874344bc8a6cf859bd39e00",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/Procfile",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/Procfile?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/72e4ef1be7c64eb0f874344bc8a6cf859bd39e00",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/Procfile"
+ }
+ },
+ {
+ "name": "README.md",
+ "path": "README.md",
+ "sha": "01aae7d562fe164d2cee644e8ef5fba82d2b8e81",
+ "size": 1589,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/README.md?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/README.md",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/01aae7d562fe164d2cee644e8ef5fba82d2b8e81",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/README.md",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/README.md?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/01aae7d562fe164d2cee644e8ef5fba82d2b8e81",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/README.md"
+ }
+ },
+ {
+ "name": "Vagrantfile.example",
+ "path": "Vagrantfile.example",
+ "sha": "54be29ea9e1e2ecdbfa642656cded8b3cb85c910",
+ "size": 4329,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/Vagrantfile.example?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/Vagrantfile.example",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/54be29ea9e1e2ecdbfa642656cded8b3cb85c910",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/Vagrantfile.example",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/Vagrantfile.example?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/54be29ea9e1e2ecdbfa642656cded8b3cb85c910",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/Vagrantfile.example"
+ }
+ },
+ {
+ "name": "app ",
+ "path": "app ",
+ "sha": "f9e84e24364972f3aa4f92b869a622db1f260fa1",
+ "size": 0,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/app%20?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/app%20",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/f9e84e24364972f3aa4f92b869a622db1f260fa1",
+ "download_url": null,
+ "type": "dir",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/app%20?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/f9e84e24364972f3aa4f92b869a622db1f260fa1",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/app%20"
+ }
+ },
+ {
+ "name": "build_scripts",
+ "path": "build_scripts",
+ "sha": "be8e80f054e47f0c9a6fc9cfe5061346c6f8b2d0",
+ "size": 0,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/build_scripts?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/build_scripts",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/be8e80f054e47f0c9a6fc9cfe5061346c6f8b2d0",
+ "download_url": null,
+ "type": "dir",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/build_scripts?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/be8e80f054e47f0c9a6fc9cfe5061346c6f8b2d0",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/build_scripts"
+ }
+ },
+ {
+ "name": "celery_worker.py",
+ "path": "celery_worker.py",
+ "sha": "c84c73c1f1c1aa42550a08ae4f32dc955ced5f18",
+ "size": 279,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/celery_worker.py?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/celery_worker.py",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/c84c73c1f1c1aa42550a08ae4f32dc955ced5f18",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/celery_worker.py",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/celery_worker.py?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/c84c73c1f1c1aa42550a08ae4f32dc955ced5f18",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/celery_worker.py"
+ }
+ },
+ {
+ "name": "config.py",
+ "path": "config.py",
+ "sha": "2886556fc4844e708472a99a85b42b4f5b51d509",
+ "size": 8250,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/config.py?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/config.py",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/2886556fc4844e708472a99a85b42b4f5b51d509",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/config.py",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/config.py?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/2886556fc4844e708472a99a85b42b4f5b51d509",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/config.py"
+ }
+ },
+ {
+ "name": "crontab",
+ "path": "crontab",
+ "sha": "1e2c1da613e8272df6ece759565524c93bc76780",
+ "size": 300,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/crontab?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/crontab",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/1e2c1da613e8272df6ece759565524c93bc76780",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/crontab",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/crontab?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/1e2c1da613e8272df6ece759565524c93bc76780",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/crontab"
+ }
+ },
+ {
+ "name": "data",
+ "path": "data",
+ "sha": "7bceca86ff0e88cb53c8828d441f5e0725776395",
+ "size": 0,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/data?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/data",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/7bceca86ff0e88cb53c8828d441f5e0725776395",
+ "download_url": null,
+ "type": "dir",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/data?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/7bceca86ff0e88cb53c8828d441f5e0725776395",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/data"
+ }
+ },
+ {
+ "name": "gunicorn_config.py",
+ "path": "gunicorn_config.py",
+ "sha": "7b1a455133c2e78611550e45e8d2072d5c5c4ad7",
+ "size": 2504,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/gunicorn_config.py?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/gunicorn_config.py",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/7b1a455133c2e78611550e45e8d2072d5c5c4ad7",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/gunicorn_config.py",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/gunicorn_config.py?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/7b1a455133c2e78611550e45e8d2072d5c5c4ad7",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/gunicorn_config.py"
+ }
+ },
+ {
+ "name": "jobs.py",
+ "path": "jobs.py",
+ "sha": "79f2957e2c94e44786f6ca3dfc7384aaceb80c0a",
+ "size": 6213,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/jobs.py?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/jobs.py",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/79f2957e2c94e44786f6ca3dfc7384aaceb80c0a",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/jobs.py",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/jobs.py?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/79f2957e2c94e44786f6ca3dfc7384aaceb80c0a",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/jobs.py"
+ }
+ },
+ {
+ "name": "magic",
+ "path": "magic",
+ "sha": "6342094c1d4b1af948867ffba67cf0b866e5613c",
+ "size": 659195,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/magic?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/magic",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/6342094c1d4b1af948867ffba67cf0b866e5613c",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/magic",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/magic?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/6342094c1d4b1af948867ffba67cf0b866e5613c",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/magic"
+ }
+ },
+ {
+ "name": "manage.py",
+ "path": "manage.py",
+ "sha": "a0b80d4c7b5fd7e50d6dcb5bcbdcd995b8da27f0",
+ "size": 15323,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/manage.py?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/manage.py",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/a0b80d4c7b5fd7e50d6dcb5bcbdcd995b8da27f0",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/manage.py",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/manage.py?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/a0b80d4c7b5fd7e50d6dcb5bcbdcd995b8da27f0",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/manage.py"
+ }
+ },
+ {
+ "name": "migrations",
+ "path": "migrations",
+ "sha": "da206a9809330d01f4800718bca2a20c05038b44",
+ "size": 0,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/migrations?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/migrations",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/da206a9809330d01f4800718bca2a20c05038b44",
+ "download_url": null,
+ "type": "dir",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/migrations?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/da206a9809330d01f4800718bca2a20c05038b44",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/migrations"
+ }
+ },
+ {
+ "name": "requirements.txt",
+ "path": "requirements.txt",
+ "sha": "88b4e0a1c8093fae2b4fa52534035f9f85ed0956",
+ "size": 2433,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/requirements.txt?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/requirements.txt",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/88b4e0a1c8093fae2b4fa52534035f9f85ed0956",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/requirements.txt",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/requirements.txt?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/88b4e0a1c8093fae2b4fa52534035f9f85ed0956",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/requirements.txt"
+ }
+ },
+ {
+ "name": "setup.py",
+ "path": "setup.py",
+ "sha": "d429264c8c2f0f306a422900c2f41123e07c31b4",
+ "size": 2433,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/setup.py?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/setup.py",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/d429264c8c2f0f306a422900c2f41123e07c31b4",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/setup.py",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/setup.py?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/d429264c8c2f0f306a422900c2f41123e07c31b4",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/setup.py"
+ }
+ },
+ {
+ "name": "tests",
+ "path": "tests",
+ "sha": "88b4e0a1c8093fae2b4fa52534035f9f85ed0956",
+ "size": 0,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/tests?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/tests",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/88b4e0a1c8093fae2b4fa52534035f9f85ed0956",
+ "download_url": null,
+ "type": "dir",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/tests?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/88b4e0a1c8093fae2b4fa52534035f9f85ed0956",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/tests"
+ }
+ },
+ {
+ "name": "todo.txt",
+ "path": "todo.txt",
+ "sha": "3e369beef1c9e64f0c10735d35aa8ad755daddc6",
+ "size": 1147,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/todo.txt?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/todo.txt",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/3e369beef1c9e64f0c10735d35aa8ad755daddc6",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/todo.txt",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/todo.txt?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/3e369beef1c9e64f0c10735d35aa8ad755daddc6",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/todo.txt"
+ }
+ },
+ {
+ "name": "update_definitions.sh",
+ "path": "update_definitions.sh",
+ "sha": "fbde266ea5ebd519b94d18f8f78ab825b02766df",
+ "size": 7877,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/update_definitions.sh?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/update_definitions.sh",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/fbde266ea5ebd519b94d18f8f78ab825b02766df",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/update_definitions.sh",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/update_definitions.sh?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/fbde266ea5ebd519b94d18f8f78ab825b02766df",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/update_definitions.sh"
+ }
+ }
+]
diff --git a/uv/spec/fixtures/github/contents_python_large_requirements_txt.json b/uv/spec/fixtures/github/contents_python_large_requirements_txt.json
new file mode 100644
index 00000000000..42bbc20c890
--- /dev/null
+++ b/uv/spec/fixtures/github/contents_python_large_requirements_txt.json
@@ -0,0 +1,18 @@
+[
+ {
+ "name": "requirements.txt",
+ "path": "requirements.txt",
+ "sha": "88b4e0a1c8093fae2b4fa52534035f9f85ed0956",
+ "size": 5000000,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/requirements.txt?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/requirements.txt",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/88b4e0a1c8093fae2b4fa52534035f9f85ed0956",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/requirements.txt",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/requirements.txt?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/88b4e0a1c8093fae2b4fa52534035f9f85ed0956",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/requirements.txt"
+ }
+ }
+]
diff --git a/uv/spec/fixtures/github/contents_python_only_pipfile_and_lockfile.json b/uv/spec/fixtures/github/contents_python_only_pipfile_and_lockfile.json
new file mode 100644
index 00000000000..d353de88713
--- /dev/null
+++ b/uv/spec/fixtures/github/contents_python_only_pipfile_and_lockfile.json
@@ -0,0 +1,434 @@
+[
+ {
+ "name": ".codeclimate.yml",
+ "path": ".codeclimate.yml",
+ "sha": "6393602fac96cfe31d64f89476014124b4a13b85",
+ "size": 416,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.codeclimate.yml?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.codeclimate.yml",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/6393602fac96cfe31d64f89476014124b4a13b85",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/.codeclimate.yml",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.codeclimate.yml?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/6393602fac96cfe31d64f89476014124b4a13b85",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.codeclimate.yml"
+ }
+ },
+ {
+ "name": ".coveragerc",
+ "path": ".coveragerc",
+ "sha": "be7fdc86067d0924f3e1e92c1a3ed92d9486fcbb",
+ "size": 646,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.coveragerc?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.coveragerc",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/be7fdc86067d0924f3e1e92c1a3ed92d9486fcbb",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/.coveragerc",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.coveragerc?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/be7fdc86067d0924f3e1e92c1a3ed92d9486fcbb",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.coveragerc"
+ }
+ },
+ {
+ "name": ".csslintrc",
+ "path": ".csslintrc",
+ "sha": "aacba956e5bbede1c195ce554fcad3e200b24ff8",
+ "size": 107,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.csslintrc?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.csslintrc",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/aacba956e5bbede1c195ce554fcad3e200b24ff8",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/.csslintrc",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.csslintrc?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/aacba956e5bbede1c195ce554fcad3e200b24ff8",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.csslintrc"
+ }
+ },
+ {
+ "name": ".env.example",
+ "path": ".env.example",
+ "sha": "d9f599b33ecd834ea88979dcc3daf4fcafacf4e7",
+ "size": 2617,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.env.example?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.env.example",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/d9f599b33ecd834ea88979dcc3daf4fcafacf4e7",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/.env.example",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.env.example?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/d9f599b33ecd834ea88979dcc3daf4fcafacf4e7",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.env.example"
+ }
+ },
+ {
+ "name": ".eslintignore",
+ "path": ".eslintignore",
+ "sha": "96212a3593bac8c93f624b77185a8d11018efd96",
+ "size": 16,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.eslintignore?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.eslintignore",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/96212a3593bac8c93f624b77185a8d11018efd96",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/.eslintignore",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.eslintignore?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/96212a3593bac8c93f624b77185a8d11018efd96",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.eslintignore"
+ }
+ },
+ {
+ "name": ".eslintrc.yml",
+ "path": ".eslintrc.yml",
+ "sha": "a6a0ce9c44238e06ff55ca335a66a4e16810da38",
+ "size": 6056,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.eslintrc.yml?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.eslintrc.yml",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/a6a0ce9c44238e06ff55ca335a66a4e16810da38",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/.eslintrc.yml",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.eslintrc.yml?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/a6a0ce9c44238e06ff55ca335a66a4e16810da38",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.eslintrc.yml"
+ }
+ },
+ {
+ "name": ".gitignore",
+ "path": ".gitignore",
+ "sha": "93923ac3a463bd17d0aefca2de9d2810f243d747",
+ "size": 1073,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.gitignore?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.gitignore",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/93923ac3a463bd17d0aefca2de9d2810f243d747",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/.gitignore",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.gitignore?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/93923ac3a463bd17d0aefca2de9d2810f243d747",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.gitignore"
+ }
+ },
+ {
+ "name": "LICENSE.md",
+ "path": "LICENSE.md",
+ "sha": "8dada3edaf50dbc082c9a125058f25def75e625a",
+ "size": 11357,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/LICENSE.md?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/LICENSE.md",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/8dada3edaf50dbc082c9a125058f25def75e625a",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/LICENSE.md",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/LICENSE.md?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/8dada3edaf50dbc082c9a125058f25def75e625a",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/LICENSE.md"
+ }
+ },
+ {
+ "name": "Procfile",
+ "path": "Procfile",
+ "sha": "72e4ef1be7c64eb0f874344bc8a6cf859bd39e00",
+ "size": 26,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/Procfile?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/Procfile",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/72e4ef1be7c64eb0f874344bc8a6cf859bd39e00",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/Procfile",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/Procfile?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/72e4ef1be7c64eb0f874344bc8a6cf859bd39e00",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/Procfile"
+ }
+ },
+ {
+ "name": "README.md",
+ "path": "README.md",
+ "sha": "01aae7d562fe164d2cee644e8ef5fba82d2b8e81",
+ "size": 1589,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/README.md?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/README.md",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/01aae7d562fe164d2cee644e8ef5fba82d2b8e81",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/README.md",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/README.md?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/01aae7d562fe164d2cee644e8ef5fba82d2b8e81",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/README.md"
+ }
+ },
+ {
+ "name": "Vagrantfile.example",
+ "path": "Vagrantfile.example",
+ "sha": "54be29ea9e1e2ecdbfa642656cded8b3cb85c910",
+ "size": 4329,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/Vagrantfile.example?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/Vagrantfile.example",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/54be29ea9e1e2ecdbfa642656cded8b3cb85c910",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/Vagrantfile.example",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/Vagrantfile.example?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/54be29ea9e1e2ecdbfa642656cded8b3cb85c910",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/Vagrantfile.example"
+ }
+ },
+ {
+ "name": "app",
+ "path": "app",
+ "sha": "f9e84e24364972f3aa4f92b869a622db1f260fa1",
+ "size": 0,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/app?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/app",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/f9e84e24364972f3aa4f92b869a622db1f260fa1",
+ "download_url": null,
+ "type": "dir",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/app?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/f9e84e24364972f3aa4f92b869a622db1f260fa1",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/app"
+ }
+ },
+ {
+ "name": "build_scripts",
+ "path": "build_scripts",
+ "sha": "be8e80f054e47f0c9a6fc9cfe5061346c6f8b2d0",
+ "size": 0,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/build_scripts?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/build_scripts",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/be8e80f054e47f0c9a6fc9cfe5061346c6f8b2d0",
+ "download_url": null,
+ "type": "dir",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/build_scripts?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/be8e80f054e47f0c9a6fc9cfe5061346c6f8b2d0",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/build_scripts"
+ }
+ },
+ {
+ "name": "celery_worker.py",
+ "path": "celery_worker.py",
+ "sha": "c84c73c1f1c1aa42550a08ae4f32dc955ced5f18",
+ "size": 279,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/celery_worker.py?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/celery_worker.py",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/c84c73c1f1c1aa42550a08ae4f32dc955ced5f18",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/celery_worker.py",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/celery_worker.py?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/c84c73c1f1c1aa42550a08ae4f32dc955ced5f18",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/celery_worker.py"
+ }
+ },
+ {
+ "name": "config.py",
+ "path": "config.py",
+ "sha": "2886556fc4844e708472a99a85b42b4f5b51d509",
+ "size": 8250,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/config.py?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/config.py",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/2886556fc4844e708472a99a85b42b4f5b51d509",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/config.py",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/config.py?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/2886556fc4844e708472a99a85b42b4f5b51d509",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/config.py"
+ }
+ },
+ {
+ "name": "crontab",
+ "path": "crontab",
+ "sha": "1e2c1da613e8272df6ece759565524c93bc76780",
+ "size": 300,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/crontab?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/crontab",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/1e2c1da613e8272df6ece759565524c93bc76780",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/crontab",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/crontab?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/1e2c1da613e8272df6ece759565524c93bc76780",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/crontab"
+ }
+ },
+ {
+ "name": "data",
+ "path": "data",
+ "sha": "7bceca86ff0e88cb53c8828d441f5e0725776395",
+ "size": 0,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/data?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/data",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/7bceca86ff0e88cb53c8828d441f5e0725776395",
+ "download_url": null,
+ "type": "dir",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/data?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/7bceca86ff0e88cb53c8828d441f5e0725776395",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/data"
+ }
+ },
+ {
+ "name": "gunicorn_config.py",
+ "path": "gunicorn_config.py",
+ "sha": "7b1a455133c2e78611550e45e8d2072d5c5c4ad7",
+ "size": 2504,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/gunicorn_config.py?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/gunicorn_config.py",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/7b1a455133c2e78611550e45e8d2072d5c5c4ad7",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/gunicorn_config.py",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/gunicorn_config.py?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/7b1a455133c2e78611550e45e8d2072d5c5c4ad7",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/gunicorn_config.py"
+ }
+ },
+ {
+ "name": "jobs.py",
+ "path": "jobs.py",
+ "sha": "79f2957e2c94e44786f6ca3dfc7384aaceb80c0a",
+ "size": 6213,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/jobs.py?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/jobs.py",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/79f2957e2c94e44786f6ca3dfc7384aaceb80c0a",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/jobs.py",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/jobs.py?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/79f2957e2c94e44786f6ca3dfc7384aaceb80c0a",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/jobs.py"
+ }
+ },
+ {
+ "name": "magic",
+ "path": "magic",
+ "sha": "6342094c1d4b1af948867ffba67cf0b866e5613c",
+ "size": 659195,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/magic?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/magic",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/6342094c1d4b1af948867ffba67cf0b866e5613c",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/magic",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/magic?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/6342094c1d4b1af948867ffba67cf0b866e5613c",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/magic"
+ }
+ },
+ {
+ "name": "manage.py",
+ "path": "manage.py",
+ "sha": "a0b80d4c7b5fd7e50d6dcb5bcbdcd995b8da27f0",
+ "size": 15323,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/manage.py?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/manage.py",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/a0b80d4c7b5fd7e50d6dcb5bcbdcd995b8da27f0",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/manage.py",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/manage.py?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/a0b80d4c7b5fd7e50d6dcb5bcbdcd995b8da27f0",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/manage.py"
+ }
+ },
+ {
+ "name": "migrations",
+ "path": "migrations",
+ "sha": "da206a9809330d01f4800718bca2a20c05038b44",
+ "size": 0,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/migrations?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/migrations",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/da206a9809330d01f4800718bca2a20c05038b44",
+ "download_url": null,
+ "type": "dir",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/migrations?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/da206a9809330d01f4800718bca2a20c05038b44",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/migrations"
+ }
+ },
+ {
+ "name": "Pipfile",
+ "path": "Pipfile",
+ "sha": "88b4e0a1c8093fae2b4fa52534035f9f85ed0956",
+ "size": 2433,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/Pipfile?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/Pipfile",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/88b4e0a1c8093fae2b4fa52534035f9f85ed0956",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/Pipfile",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/Pipfile?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/88b4e0a1c8093fae2b4fa52534035f9f85ed0956",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/Pipfile"
+ }
+ },
+ {
+ "name": "Pipfile.lock",
+ "path": "Pipfile.lock",
+ "sha": "d429264c8c2f0f306a422900c2f41123e07c31b4",
+ "size": 2433,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/Pipfile.lock?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/Pipfile.lock",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/d429264c8c2f0f306a422900c2f41123e07c31b4",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/Pipfile.lock",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/Pipfile.lock?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/d429264c8c2f0f306a422900c2f41123e07c31b4",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/Pipfile.lock"
+ }
+ },
+ {
+ "name": "tests",
+ "path": "tests",
+ "sha": "88b4e0a1c8093fae2b4fa52534035f9f85ed0956",
+ "size": 0,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/tests?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/tests",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/88b4e0a1c8093fae2b4fa52534035f9f85ed0956",
+ "download_url": null,
+ "type": "dir",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/tests?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/88b4e0a1c8093fae2b4fa52534035f9f85ed0956",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/tests"
+ }
+ },
+ {
+ "name": "todo.txt",
+ "path": "todo.txt",
+ "sha": "3e369beef1c9e64f0c10735d35aa8ad755daddc6",
+ "size": 1147,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/todo.txt?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/todo.txt",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/3e369beef1c9e64f0c10735d35aa8ad755daddc6",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/todo.txt",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/todo.txt?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/3e369beef1c9e64f0c10735d35aa8ad755daddc6",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/todo.txt"
+ }
+ },
+ {
+ "name": "update_definitions.sh",
+ "path": "update_definitions.sh",
+ "sha": "fbde266ea5ebd519b94d18f8f78ab825b02766df",
+ "size": 7877,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/update_definitions.sh?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/update_definitions.sh",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/fbde266ea5ebd519b94d18f8f78ab825b02766df",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/update_definitions.sh",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/update_definitions.sh?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/fbde266ea5ebd519b94d18f8f78ab825b02766df",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/update_definitions.sh"
+ }
+ }
+]
diff --git a/uv/spec/fixtures/github/contents_python_only_pyproject.json b/uv/spec/fixtures/github/contents_python_only_pyproject.json
new file mode 100644
index 00000000000..1359612ea67
--- /dev/null
+++ b/uv/spec/fixtures/github/contents_python_only_pyproject.json
@@ -0,0 +1,242 @@
+[
+ {
+ "name": ".coveragerc",
+ "path": ".coveragerc",
+ "sha": "73ec6b729bfbb906d63ce7f63af65e5e50e0c97f",
+ "size": 176,
+ "url": "https://api.github.com/repos/sdispater/pendulum/contents/.coveragerc?ref=master",
+ "html_url": "https://github.com/sdispater/pendulum/blob/master/.coveragerc",
+ "git_url": "https://api.github.com/repos/sdispater/pendulum/git/blobs/73ec6b729bfbb906d63ce7f63af65e5e50e0c97f",
+ "download_url": "https://raw.githubusercontent.com/sdispater/pendulum/master/.coveragerc",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/sdispater/pendulum/contents/.coveragerc?ref=master",
+ "git": "https://api.github.com/repos/sdispater/pendulum/git/blobs/73ec6b729bfbb906d63ce7f63af65e5e50e0c97f",
+ "html": "https://github.com/sdispater/pendulum/blob/master/.coveragerc"
+ }
+ },
+ {
+ "name": ".gitignore",
+ "path": ".gitignore",
+ "sha": "f1152e6f31ab32173b895e1dfe19ae4fa68ac4ef",
+ "size": 335,
+ "url": "https://api.github.com/repos/sdispater/pendulum/contents/.gitignore?ref=master",
+ "html_url": "https://github.com/sdispater/pendulum/blob/master/.gitignore",
+ "git_url": "https://api.github.com/repos/sdispater/pendulum/git/blobs/f1152e6f31ab32173b895e1dfe19ae4fa68ac4ef",
+ "download_url": "https://raw.githubusercontent.com/sdispater/pendulum/master/.gitignore",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/sdispater/pendulum/contents/.gitignore?ref=master",
+ "git": "https://api.github.com/repos/sdispater/pendulum/git/blobs/f1152e6f31ab32173b895e1dfe19ae4fa68ac4ef",
+ "html": "https://github.com/sdispater/pendulum/blob/master/.gitignore"
+ }
+ },
+ {
+ "name": ".travis.yml",
+ "path": ".travis.yml",
+ "sha": "6078c0f77b8e920b479ec0bde20a161895d760a1",
+ "size": 1831,
+ "url": "https://api.github.com/repos/sdispater/pendulum/contents/.travis.yml?ref=master",
+ "html_url": "https://github.com/sdispater/pendulum/blob/master/.travis.yml",
+ "git_url": "https://api.github.com/repos/sdispater/pendulum/git/blobs/6078c0f77b8e920b479ec0bde20a161895d760a1",
+ "download_url": "https://raw.githubusercontent.com/sdispater/pendulum/master/.travis.yml",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/sdispater/pendulum/contents/.travis.yml?ref=master",
+ "git": "https://api.github.com/repos/sdispater/pendulum/git/blobs/6078c0f77b8e920b479ec0bde20a161895d760a1",
+ "html": "https://github.com/sdispater/pendulum/blob/master/.travis.yml"
+ }
+ },
+ {
+ "name": "CHANGELOG.md",
+ "path": "CHANGELOG.md",
+ "sha": "c4bccb2d630f660a2d3d904e3c69a10622b2bbdf",
+ "size": 2721,
+ "url": "https://api.github.com/repos/sdispater/pendulum/contents/CHANGELOG.md?ref=master",
+ "html_url": "https://github.com/sdispater/pendulum/blob/master/CHANGELOG.md",
+ "git_url": "https://api.github.com/repos/sdispater/pendulum/git/blobs/c4bccb2d630f660a2d3d904e3c69a10622b2bbdf",
+ "download_url": "https://raw.githubusercontent.com/sdispater/pendulum/master/CHANGELOG.md",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/sdispater/pendulum/contents/CHANGELOG.md?ref=master",
+ "git": "https://api.github.com/repos/sdispater/pendulum/git/blobs/c4bccb2d630f660a2d3d904e3c69a10622b2bbdf",
+ "html": "https://github.com/sdispater/pendulum/blob/master/CHANGELOG.md"
+ }
+ },
+ {
+ "name": "LICENSE",
+ "path": "LICENSE",
+ "sha": "701df228d97e9bf3f2b10c5634107daff2f7bd3d",
+ "size": 1062,
+ "url": "https://api.github.com/repos/sdispater/pendulum/contents/LICENSE?ref=master",
+ "html_url": "https://github.com/sdispater/pendulum/blob/master/LICENSE",
+ "git_url": "https://api.github.com/repos/sdispater/pendulum/git/blobs/701df228d97e9bf3f2b10c5634107daff2f7bd3d",
+ "download_url": "https://raw.githubusercontent.com/sdispater/pendulum/master/LICENSE",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/sdispater/pendulum/contents/LICENSE?ref=master",
+ "git": "https://api.github.com/repos/sdispater/pendulum/git/blobs/701df228d97e9bf3f2b10c5634107daff2f7bd3d",
+ "html": "https://github.com/sdispater/pendulum/blob/master/LICENSE"
+ }
+ },
+ {
+ "name": "Makefile",
+ "path": "Makefile",
+ "sha": "a3a3ef448f0e9dbe0ed0849d19d74cbc2e93607f",
+ "size": 1568,
+ "url": "https://api.github.com/repos/sdispater/pendulum/contents/Makefile?ref=master",
+ "html_url": "https://github.com/sdispater/pendulum/blob/master/Makefile",
+ "git_url": "https://api.github.com/repos/sdispater/pendulum/git/blobs/a3a3ef448f0e9dbe0ed0849d19d74cbc2e93607f",
+ "download_url": "https://raw.githubusercontent.com/sdispater/pendulum/master/Makefile",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/sdispater/pendulum/contents/Makefile?ref=master",
+ "git": "https://api.github.com/repos/sdispater/pendulum/git/blobs/a3a3ef448f0e9dbe0ed0849d19d74cbc2e93607f",
+ "html": "https://github.com/sdispater/pendulum/blob/master/Makefile"
+ }
+ },
+ {
+ "name": "README.rst",
+ "path": "README.rst",
+ "sha": "70f59df8e74705a3392b6b87804e882a50c6dda6",
+ "size": 7409,
+ "url": "https://api.github.com/repos/sdispater/pendulum/contents/README.rst?ref=master",
+ "html_url": "https://github.com/sdispater/pendulum/blob/master/README.rst",
+ "git_url": "https://api.github.com/repos/sdispater/pendulum/git/blobs/70f59df8e74705a3392b6b87804e882a50c6dda6",
+ "download_url": "https://raw.githubusercontent.com/sdispater/pendulum/master/README.rst",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/sdispater/pendulum/contents/README.rst?ref=master",
+ "git": "https://api.github.com/repos/sdispater/pendulum/git/blobs/70f59df8e74705a3392b6b87804e882a50c6dda6",
+ "html": "https://github.com/sdispater/pendulum/blob/master/README.rst"
+ }
+ },
+ {
+ "name": "appveyor.yml",
+ "path": "appveyor.yml",
+ "sha": "55cba3cc7d675f63a233f03cbe03b9265f9c7af7",
+ "size": 856,
+ "url": "https://api.github.com/repos/sdispater/pendulum/contents/appveyor.yml?ref=master",
+ "html_url": "https://github.com/sdispater/pendulum/blob/master/appveyor.yml",
+ "git_url": "https://api.github.com/repos/sdispater/pendulum/git/blobs/55cba3cc7d675f63a233f03cbe03b9265f9c7af7",
+ "download_url": "https://raw.githubusercontent.com/sdispater/pendulum/master/appveyor.yml",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/sdispater/pendulum/contents/appveyor.yml?ref=master",
+ "git": "https://api.github.com/repos/sdispater/pendulum/git/blobs/55cba3cc7d675f63a233f03cbe03b9265f9c7af7",
+ "html": "https://github.com/sdispater/pendulum/blob/master/appveyor.yml"
+ }
+ },
+ {
+ "name": "build-wheels.sh",
+ "path": "build-wheels.sh",
+ "sha": "83a4d1e7b3a75152e42685750c44d631fe7ffbb6",
+ "size": 1415,
+ "url": "https://api.github.com/repos/sdispater/pendulum/contents/build-wheels.sh?ref=master",
+ "html_url": "https://github.com/sdispater/pendulum/blob/master/build-wheels.sh",
+ "git_url": "https://api.github.com/repos/sdispater/pendulum/git/blobs/83a4d1e7b3a75152e42685750c44d631fe7ffbb6",
+ "download_url": "https://raw.githubusercontent.com/sdispater/pendulum/master/build-wheels.sh",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/sdispater/pendulum/contents/build-wheels.sh?ref=master",
+ "git": "https://api.github.com/repos/sdispater/pendulum/git/blobs/83a4d1e7b3a75152e42685750c44d631fe7ffbb6",
+ "html": "https://github.com/sdispater/pendulum/blob/master/build-wheels.sh"
+ }
+ },
+ {
+ "name": "build.py",
+ "path": "build.py",
+ "sha": "097d14faa10f114e281e65d3d2d3da45ad4dc516",
+ "size": 2116,
+ "url": "https://api.github.com/repos/sdispater/pendulum/contents/build.py?ref=master",
+ "html_url": "https://github.com/sdispater/pendulum/blob/master/build.py",
+ "git_url": "https://api.github.com/repos/sdispater/pendulum/git/blobs/097d14faa10f114e281e65d3d2d3da45ad4dc516",
+ "download_url": "https://raw.githubusercontent.com/sdispater/pendulum/master/build.py",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/sdispater/pendulum/contents/build.py?ref=master",
+ "git": "https://api.github.com/repos/sdispater/pendulum/git/blobs/097d14faa10f114e281e65d3d2d3da45ad4dc516",
+ "html": "https://github.com/sdispater/pendulum/blob/master/build.py"
+ }
+ },
+ {
+ "name": "clock",
+ "path": "clock",
+ "sha": "c4c0f180b92bdbab1c27e3a210de5219e8d5b007",
+ "size": 7917,
+ "url": "https://api.github.com/repos/sdispater/pendulum/contents/clock?ref=master",
+ "html_url": "https://github.com/sdispater/pendulum/blob/master/clock",
+ "git_url": "https://api.github.com/repos/sdispater/pendulum/git/blobs/c4c0f180b92bdbab1c27e3a210de5219e8d5b007",
+ "download_url": "https://raw.githubusercontent.com/sdispater/pendulum/master/clock",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/sdispater/pendulum/contents/clock?ref=master",
+ "git": "https://api.github.com/repos/sdispater/pendulum/git/blobs/c4c0f180b92bdbab1c27e3a210de5219e8d5b007",
+ "html": "https://github.com/sdispater/pendulum/blob/master/clock"
+ }
+ },
+ {
+ "name": "codecov.yml",
+ "path": "codecov.yml",
+ "sha": "3cbba2876f8581b69de8fa55746e3700bd415f6d",
+ "size": 85,
+ "url": "https://api.github.com/repos/sdispater/pendulum/contents/codecov.yml?ref=master",
+ "html_url": "https://github.com/sdispater/pendulum/blob/master/codecov.yml",
+ "git_url": "https://api.github.com/repos/sdispater/pendulum/git/blobs/3cbba2876f8581b69de8fa55746e3700bd415f6d",
+ "download_url": "https://raw.githubusercontent.com/sdispater/pendulum/master/codecov.yml",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/sdispater/pendulum/contents/codecov.yml?ref=master",
+ "git": "https://api.github.com/repos/sdispater/pendulum/git/blobs/3cbba2876f8581b69de8fa55746e3700bd415f6d",
+ "html": "https://github.com/sdispater/pendulum/blob/master/codecov.yml"
+ }
+ },
+ {
+ "name": "pyproject.toml",
+ "path": "pyproject.toml",
+ "sha": "e003114331b9777c5ff4bf3915ae98f08a972a41",
+ "size": 709,
+ "url": "https://api.github.com/repos/sdispater/pendulum/contents/pyproject.toml?ref=master",
+ "html_url": "https://github.com/sdispater/pendulum/blob/master/pyproject.toml",
+ "git_url": "https://api.github.com/repos/sdispater/pendulum/git/blobs/e003114331b9777c5ff4bf3915ae98f08a972a41",
+ "download_url": "https://raw.githubusercontent.com/sdispater/pendulum/master/pyproject.toml",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/sdispater/pendulum/contents/pyproject.toml?ref=master",
+ "git": "https://api.github.com/repos/sdispater/pendulum/git/blobs/e003114331b9777c5ff4bf3915ae98f08a972a41",
+ "html": "https://github.com/sdispater/pendulum/blob/master/pyproject.toml"
+ }
+ },
+ {
+ "name": "tests",
+ "path": "tests",
+ "sha": "f09909434d110482e86b36bdb68182b3dc951095",
+ "size": 0,
+ "url": "https://api.github.com/repos/sdispater/pendulum/contents/tests?ref=master",
+ "html_url": "https://github.com/sdispater/pendulum/tree/master/tests",
+ "git_url": "https://api.github.com/repos/sdispater/pendulum/git/trees/f09909434d110482e86b36bdb68182b3dc951095",
+ "download_url": null,
+ "type": "dir",
+ "_links": {
+ "self": "https://api.github.com/repos/sdispater/pendulum/contents/tests?ref=master",
+ "git": "https://api.github.com/repos/sdispater/pendulum/git/trees/f09909434d110482e86b36bdb68182b3dc951095",
+ "html": "https://github.com/sdispater/pendulum/tree/master/tests"
+ }
+ },
+ {
+ "name": "tox.ini",
+ "path": "tox.ini",
+ "sha": "072640ccb4e1a591c32af70dbb3245e29ca482ac",
+ "size": 325,
+ "url": "https://api.github.com/repos/sdispater/pendulum/contents/tox.ini?ref=master",
+ "html_url": "https://github.com/sdispater/pendulum/blob/master/tox.ini",
+ "git_url": "https://api.github.com/repos/sdispater/pendulum/git/blobs/072640ccb4e1a591c32af70dbb3245e29ca482ac",
+ "download_url": "https://raw.githubusercontent.com/sdispater/pendulum/master/tox.ini",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/sdispater/pendulum/contents/tox.ini?ref=master",
+ "git": "https://api.github.com/repos/sdispater/pendulum/git/blobs/072640ccb4e1a591c32af70dbb3245e29ca482ac",
+ "html": "https://github.com/sdispater/pendulum/blob/master/tox.ini"
+ }
+ }
+]
diff --git a/uv/spec/fixtures/github/contents_python_only_requirements.json b/uv/spec/fixtures/github/contents_python_only_requirements.json
new file mode 100644
index 00000000000..d8eeb06262b
--- /dev/null
+++ b/uv/spec/fixtures/github/contents_python_only_requirements.json
@@ -0,0 +1,418 @@
+[
+ {
+ "name": ".codeclimate.yml",
+ "path": ".codeclimate.yml",
+ "sha": "6393602fac96cfe31d64f89476014124b4a13b85",
+ "size": 416,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.codeclimate.yml?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.codeclimate.yml",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/6393602fac96cfe31d64f89476014124b4a13b85",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/.codeclimate.yml",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.codeclimate.yml?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/6393602fac96cfe31d64f89476014124b4a13b85",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.codeclimate.yml"
+ }
+ },
+ {
+ "name": ".coveragerc",
+ "path": ".coveragerc",
+ "sha": "be7fdc86067d0924f3e1e92c1a3ed92d9486fcbb",
+ "size": 646,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.coveragerc?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.coveragerc",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/be7fdc86067d0924f3e1e92c1a3ed92d9486fcbb",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/.coveragerc",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.coveragerc?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/be7fdc86067d0924f3e1e92c1a3ed92d9486fcbb",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.coveragerc"
+ }
+ },
+ {
+ "name": ".csslintrc",
+ "path": ".csslintrc",
+ "sha": "aacba956e5bbede1c195ce554fcad3e200b24ff8",
+ "size": 107,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.csslintrc?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.csslintrc",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/aacba956e5bbede1c195ce554fcad3e200b24ff8",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/.csslintrc",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.csslintrc?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/aacba956e5bbede1c195ce554fcad3e200b24ff8",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.csslintrc"
+ }
+ },
+ {
+ "name": ".env.example",
+ "path": ".env.example",
+ "sha": "d9f599b33ecd834ea88979dcc3daf4fcafacf4e7",
+ "size": 2617,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.env.example?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.env.example",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/d9f599b33ecd834ea88979dcc3daf4fcafacf4e7",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/.env.example",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.env.example?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/d9f599b33ecd834ea88979dcc3daf4fcafacf4e7",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.env.example"
+ }
+ },
+ {
+ "name": ".eslintignore",
+ "path": ".eslintignore",
+ "sha": "96212a3593bac8c93f624b77185a8d11018efd96",
+ "size": 16,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.eslintignore?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.eslintignore",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/96212a3593bac8c93f624b77185a8d11018efd96",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/.eslintignore",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.eslintignore?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/96212a3593bac8c93f624b77185a8d11018efd96",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.eslintignore"
+ }
+ },
+ {
+ "name": ".eslintrc.yml",
+ "path": ".eslintrc.yml",
+ "sha": "a6a0ce9c44238e06ff55ca335a66a4e16810da38",
+ "size": 6056,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.eslintrc.yml?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.eslintrc.yml",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/a6a0ce9c44238e06ff55ca335a66a4e16810da38",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/.eslintrc.yml",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.eslintrc.yml?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/a6a0ce9c44238e06ff55ca335a66a4e16810da38",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.eslintrc.yml"
+ }
+ },
+ {
+ "name": ".gitignore",
+ "path": ".gitignore",
+ "sha": "93923ac3a463bd17d0aefca2de9d2810f243d747",
+ "size": 1073,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.gitignore?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.gitignore",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/93923ac3a463bd17d0aefca2de9d2810f243d747",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/.gitignore",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.gitignore?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/93923ac3a463bd17d0aefca2de9d2810f243d747",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.gitignore"
+ }
+ },
+ {
+ "name": "LICENSE.md",
+ "path": "LICENSE.md",
+ "sha": "8dada3edaf50dbc082c9a125058f25def75e625a",
+ "size": 11357,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/LICENSE.md?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/LICENSE.md",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/8dada3edaf50dbc082c9a125058f25def75e625a",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/LICENSE.md",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/LICENSE.md?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/8dada3edaf50dbc082c9a125058f25def75e625a",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/LICENSE.md"
+ }
+ },
+ {
+ "name": "Procfile",
+ "path": "Procfile",
+ "sha": "72e4ef1be7c64eb0f874344bc8a6cf859bd39e00",
+ "size": 26,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/Procfile?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/Procfile",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/72e4ef1be7c64eb0f874344bc8a6cf859bd39e00",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/Procfile",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/Procfile?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/72e4ef1be7c64eb0f874344bc8a6cf859bd39e00",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/Procfile"
+ }
+ },
+ {
+ "name": "README.md",
+ "path": "README.md",
+ "sha": "01aae7d562fe164d2cee644e8ef5fba82d2b8e81",
+ "size": 1589,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/README.md?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/README.md",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/01aae7d562fe164d2cee644e8ef5fba82d2b8e81",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/README.md",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/README.md?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/01aae7d562fe164d2cee644e8ef5fba82d2b8e81",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/README.md"
+ }
+ },
+ {
+ "name": "Vagrantfile.example",
+ "path": "Vagrantfile.example",
+ "sha": "54be29ea9e1e2ecdbfa642656cded8b3cb85c910",
+ "size": 4329,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/Vagrantfile.example?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/Vagrantfile.example",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/54be29ea9e1e2ecdbfa642656cded8b3cb85c910",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/Vagrantfile.example",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/Vagrantfile.example?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/54be29ea9e1e2ecdbfa642656cded8b3cb85c910",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/Vagrantfile.example"
+ }
+ },
+ {
+ "name": "app",
+ "path": "app",
+ "sha": "f9e84e24364972f3aa4f92b869a622db1f260fa1",
+ "size": 0,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/app?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/app",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/f9e84e24364972f3aa4f92b869a622db1f260fa1",
+ "download_url": null,
+ "type": "dir",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/app?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/f9e84e24364972f3aa4f92b869a622db1f260fa1",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/app"
+ }
+ },
+ {
+ "name": "build_scripts",
+ "path": "build_scripts",
+ "sha": "be8e80f054e47f0c9a6fc9cfe5061346c6f8b2d0",
+ "size": 0,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/build_scripts?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/build_scripts",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/be8e80f054e47f0c9a6fc9cfe5061346c6f8b2d0",
+ "download_url": null,
+ "type": "dir",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/build_scripts?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/be8e80f054e47f0c9a6fc9cfe5061346c6f8b2d0",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/build_scripts"
+ }
+ },
+ {
+ "name": "celery_worker.py",
+ "path": "celery_worker.py",
+ "sha": "c84c73c1f1c1aa42550a08ae4f32dc955ced5f18",
+ "size": 279,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/celery_worker.py?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/celery_worker.py",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/c84c73c1f1c1aa42550a08ae4f32dc955ced5f18",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/celery_worker.py",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/celery_worker.py?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/c84c73c1f1c1aa42550a08ae4f32dc955ced5f18",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/celery_worker.py"
+ }
+ },
+ {
+ "name": "config.py",
+ "path": "config.py",
+ "sha": "2886556fc4844e708472a99a85b42b4f5b51d509",
+ "size": 8250,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/config.py?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/config.py",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/2886556fc4844e708472a99a85b42b4f5b51d509",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/config.py",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/config.py?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/2886556fc4844e708472a99a85b42b4f5b51d509",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/config.py"
+ }
+ },
+ {
+ "name": "crontab",
+ "path": "crontab",
+ "sha": "1e2c1da613e8272df6ece759565524c93bc76780",
+ "size": 300,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/crontab?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/crontab",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/1e2c1da613e8272df6ece759565524c93bc76780",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/crontab",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/crontab?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/1e2c1da613e8272df6ece759565524c93bc76780",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/crontab"
+ }
+ },
+ {
+ "name": "data",
+ "path": "data",
+ "sha": "7bceca86ff0e88cb53c8828d441f5e0725776395",
+ "size": 0,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/data?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/data",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/7bceca86ff0e88cb53c8828d441f5e0725776395",
+ "download_url": null,
+ "type": "dir",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/data?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/7bceca86ff0e88cb53c8828d441f5e0725776395",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/data"
+ }
+ },
+ {
+ "name": "gunicorn_config.py",
+ "path": "gunicorn_config.py",
+ "sha": "7b1a455133c2e78611550e45e8d2072d5c5c4ad7",
+ "size": 2504,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/gunicorn_config.py?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/gunicorn_config.py",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/7b1a455133c2e78611550e45e8d2072d5c5c4ad7",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/gunicorn_config.py",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/gunicorn_config.py?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/7b1a455133c2e78611550e45e8d2072d5c5c4ad7",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/gunicorn_config.py"
+ }
+ },
+ {
+ "name": "jobs.py",
+ "path": "jobs.py",
+ "sha": "79f2957e2c94e44786f6ca3dfc7384aaceb80c0a",
+ "size": 6213,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/jobs.py?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/jobs.py",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/79f2957e2c94e44786f6ca3dfc7384aaceb80c0a",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/jobs.py",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/jobs.py?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/79f2957e2c94e44786f6ca3dfc7384aaceb80c0a",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/jobs.py"
+ }
+ },
+ {
+ "name": "magic",
+ "path": "magic",
+ "sha": "6342094c1d4b1af948867ffba67cf0b866e5613c",
+ "size": 659195,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/magic?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/magic",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/6342094c1d4b1af948867ffba67cf0b866e5613c",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/magic",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/magic?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/6342094c1d4b1af948867ffba67cf0b866e5613c",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/magic"
+ }
+ },
+ {
+ "name": "manage.py",
+ "path": "manage.py",
+ "sha": "a0b80d4c7b5fd7e50d6dcb5bcbdcd995b8da27f0",
+ "size": 15323,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/manage.py?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/manage.py",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/a0b80d4c7b5fd7e50d6dcb5bcbdcd995b8da27f0",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/manage.py",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/manage.py?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/a0b80d4c7b5fd7e50d6dcb5bcbdcd995b8da27f0",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/manage.py"
+ }
+ },
+ {
+ "name": "migrations",
+ "path": "migrations",
+ "sha": "da206a9809330d01f4800718bca2a20c05038b44",
+ "size": 0,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/migrations?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/migrations",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/da206a9809330d01f4800718bca2a20c05038b44",
+ "download_url": null,
+ "type": "dir",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/migrations?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/da206a9809330d01f4800718bca2a20c05038b44",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/migrations"
+ }
+ },
+ {
+ "name": "requirements.txt",
+ "path": "requirements.txt",
+ "sha": "88b4e0a1c8093fae2b4fa52534035f9f85ed0956",
+ "size": 2433,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/requirements.txt?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/requirements.txt",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/88b4e0a1c8093fae2b4fa52534035f9f85ed0956",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/requirements.txt",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/requirements.txt?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/88b4e0a1c8093fae2b4fa52534035f9f85ed0956",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/requirements.txt"
+ }
+ },
+ {
+ "name": "tests",
+ "path": "tests",
+ "sha": "88b4e0a1c8093fae2b4fa52534035f9f85ed0956",
+ "size": 0,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/tests?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/tests",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/88b4e0a1c8093fae2b4fa52534035f9f85ed0956",
+ "download_url": null,
+ "type": "dir",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/tests?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/88b4e0a1c8093fae2b4fa52534035f9f85ed0956",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/tests"
+ }
+ },
+ {
+ "name": "todo.txt",
+ "path": "todo.txt",
+ "sha": "3e369beef1c9e64f0c10735d35aa8ad755daddc6",
+ "size": 1147,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/todo.txt?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/todo.txt",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/3e369beef1c9e64f0c10735d35aa8ad755daddc6",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/todo.txt",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/todo.txt?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/3e369beef1c9e64f0c10735d35aa8ad755daddc6",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/todo.txt"
+ }
+ },
+ {
+ "name": "update_definitions.sh",
+ "path": "update_definitions.sh",
+ "sha": "fbde266ea5ebd519b94d18f8f78ab825b02766df",
+ "size": 7877,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/update_definitions.sh?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/update_definitions.sh",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/fbde266ea5ebd519b94d18f8f78ab825b02766df",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/update_definitions.sh",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/update_definitions.sh?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/fbde266ea5ebd519b94d18f8f78ab825b02766df",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/update_definitions.sh"
+ }
+ }
+]
diff --git a/uv/spec/fixtures/github/contents_python_only_requirements_in.json b/uv/spec/fixtures/github/contents_python_only_requirements_in.json
new file mode 100644
index 00000000000..28867c34ca0
--- /dev/null
+++ b/uv/spec/fixtures/github/contents_python_only_requirements_in.json
@@ -0,0 +1,418 @@
+[
+ {
+ "name": ".codeclimate.yml",
+ "path": ".codeclimate.yml",
+ "sha": "6393602fac96cfe31d64f89476014124b4a13b85",
+ "size": 416,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.codeclimate.yml?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.codeclimate.yml",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/6393602fac96cfe31d64f89476014124b4a13b85",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/.codeclimate.yml",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.codeclimate.yml?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/6393602fac96cfe31d64f89476014124b4a13b85",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.codeclimate.yml"
+ }
+ },
+ {
+ "name": ".coveragerc",
+ "path": ".coveragerc",
+ "sha": "be7fdc86067d0924f3e1e92c1a3ed92d9486fcbb",
+ "size": 646,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.coveragerc?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.coveragerc",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/be7fdc86067d0924f3e1e92c1a3ed92d9486fcbb",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/.coveragerc",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.coveragerc?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/be7fdc86067d0924f3e1e92c1a3ed92d9486fcbb",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.coveragerc"
+ }
+ },
+ {
+ "name": ".csslintrc",
+ "path": ".csslintrc",
+ "sha": "aacba956e5bbede1c195ce554fcad3e200b24ff8",
+ "size": 107,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.csslintrc?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.csslintrc",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/aacba956e5bbede1c195ce554fcad3e200b24ff8",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/.csslintrc",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.csslintrc?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/aacba956e5bbede1c195ce554fcad3e200b24ff8",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.csslintrc"
+ }
+ },
+ {
+ "name": ".env.example",
+ "path": ".env.example",
+ "sha": "d9f599b33ecd834ea88979dcc3daf4fcafacf4e7",
+ "size": 2617,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.env.example?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.env.example",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/d9f599b33ecd834ea88979dcc3daf4fcafacf4e7",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/.env.example",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.env.example?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/d9f599b33ecd834ea88979dcc3daf4fcafacf4e7",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.env.example"
+ }
+ },
+ {
+ "name": ".eslintignore",
+ "path": ".eslintignore",
+ "sha": "96212a3593bac8c93f624b77185a8d11018efd96",
+ "size": 16,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.eslintignore?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.eslintignore",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/96212a3593bac8c93f624b77185a8d11018efd96",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/.eslintignore",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.eslintignore?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/96212a3593bac8c93f624b77185a8d11018efd96",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.eslintignore"
+ }
+ },
+ {
+ "name": ".eslintrc.yml",
+ "path": ".eslintrc.yml",
+ "sha": "a6a0ce9c44238e06ff55ca335a66a4e16810da38",
+ "size": 6056,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.eslintrc.yml?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.eslintrc.yml",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/a6a0ce9c44238e06ff55ca335a66a4e16810da38",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/.eslintrc.yml",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.eslintrc.yml?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/a6a0ce9c44238e06ff55ca335a66a4e16810da38",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.eslintrc.yml"
+ }
+ },
+ {
+ "name": ".gitignore",
+ "path": ".gitignore",
+ "sha": "93923ac3a463bd17d0aefca2de9d2810f243d747",
+ "size": 1073,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.gitignore?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.gitignore",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/93923ac3a463bd17d0aefca2de9d2810f243d747",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/.gitignore",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.gitignore?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/93923ac3a463bd17d0aefca2de9d2810f243d747",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.gitignore"
+ }
+ },
+ {
+ "name": "LICENSE.md",
+ "path": "LICENSE.md",
+ "sha": "8dada3edaf50dbc082c9a125058f25def75e625a",
+ "size": 11357,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/LICENSE.md?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/LICENSE.md",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/8dada3edaf50dbc082c9a125058f25def75e625a",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/LICENSE.md",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/LICENSE.md?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/8dada3edaf50dbc082c9a125058f25def75e625a",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/LICENSE.md"
+ }
+ },
+ {
+ "name": "Procfile",
+ "path": "Procfile",
+ "sha": "72e4ef1be7c64eb0f874344bc8a6cf859bd39e00",
+ "size": 26,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/Procfile?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/Procfile",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/72e4ef1be7c64eb0f874344bc8a6cf859bd39e00",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/Procfile",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/Procfile?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/72e4ef1be7c64eb0f874344bc8a6cf859bd39e00",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/Procfile"
+ }
+ },
+ {
+ "name": "README.md",
+ "path": "README.md",
+ "sha": "01aae7d562fe164d2cee644e8ef5fba82d2b8e81",
+ "size": 1589,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/README.md?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/README.md",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/01aae7d562fe164d2cee644e8ef5fba82d2b8e81",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/README.md",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/README.md?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/01aae7d562fe164d2cee644e8ef5fba82d2b8e81",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/README.md"
+ }
+ },
+ {
+ "name": "Vagrantfile.example",
+ "path": "Vagrantfile.example",
+ "sha": "54be29ea9e1e2ecdbfa642656cded8b3cb85c910",
+ "size": 4329,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/Vagrantfile.example?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/Vagrantfile.example",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/54be29ea9e1e2ecdbfa642656cded8b3cb85c910",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/Vagrantfile.example",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/Vagrantfile.example?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/54be29ea9e1e2ecdbfa642656cded8b3cb85c910",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/Vagrantfile.example"
+ }
+ },
+ {
+ "name": "app",
+ "path": "app",
+ "sha": "f9e84e24364972f3aa4f92b869a622db1f260fa1",
+ "size": 0,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/app?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/app",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/f9e84e24364972f3aa4f92b869a622db1f260fa1",
+ "download_url": null,
+ "type": "dir",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/app?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/f9e84e24364972f3aa4f92b869a622db1f260fa1",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/app"
+ }
+ },
+ {
+ "name": "build_scripts",
+ "path": "build_scripts",
+ "sha": "be8e80f054e47f0c9a6fc9cfe5061346c6f8b2d0",
+ "size": 0,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/build_scripts?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/build_scripts",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/be8e80f054e47f0c9a6fc9cfe5061346c6f8b2d0",
+ "download_url": null,
+ "type": "dir",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/build_scripts?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/be8e80f054e47f0c9a6fc9cfe5061346c6f8b2d0",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/build_scripts"
+ }
+ },
+ {
+ "name": "celery_worker.py",
+ "path": "celery_worker.py",
+ "sha": "c84c73c1f1c1aa42550a08ae4f32dc955ced5f18",
+ "size": 279,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/celery_worker.py?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/celery_worker.py",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/c84c73c1f1c1aa42550a08ae4f32dc955ced5f18",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/celery_worker.py",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/celery_worker.py?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/c84c73c1f1c1aa42550a08ae4f32dc955ced5f18",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/celery_worker.py"
+ }
+ },
+ {
+ "name": "config.py",
+ "path": "config.py",
+ "sha": "2886556fc4844e708472a99a85b42b4f5b51d509",
+ "size": 8250,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/config.py?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/config.py",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/2886556fc4844e708472a99a85b42b4f5b51d509",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/config.py",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/config.py?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/2886556fc4844e708472a99a85b42b4f5b51d509",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/config.py"
+ }
+ },
+ {
+ "name": "crontab",
+ "path": "crontab",
+ "sha": "1e2c1da613e8272df6ece759565524c93bc76780",
+ "size": 300,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/crontab?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/crontab",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/1e2c1da613e8272df6ece759565524c93bc76780",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/crontab",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/crontab?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/1e2c1da613e8272df6ece759565524c93bc76780",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/crontab"
+ }
+ },
+ {
+ "name": "data",
+ "path": "data",
+ "sha": "7bceca86ff0e88cb53c8828d441f5e0725776395",
+ "size": 0,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/data?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/data",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/7bceca86ff0e88cb53c8828d441f5e0725776395",
+ "download_url": null,
+ "type": "dir",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/data?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/7bceca86ff0e88cb53c8828d441f5e0725776395",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/data"
+ }
+ },
+ {
+ "name": "gunicorn_config.py",
+ "path": "gunicorn_config.py",
+ "sha": "7b1a455133c2e78611550e45e8d2072d5c5c4ad7",
+ "size": 2504,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/gunicorn_config.py?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/gunicorn_config.py",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/7b1a455133c2e78611550e45e8d2072d5c5c4ad7",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/gunicorn_config.py",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/gunicorn_config.py?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/7b1a455133c2e78611550e45e8d2072d5c5c4ad7",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/gunicorn_config.py"
+ }
+ },
+ {
+ "name": "jobs.py",
+ "path": "jobs.py",
+ "sha": "79f2957e2c94e44786f6ca3dfc7384aaceb80c0a",
+ "size": 6213,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/jobs.py?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/jobs.py",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/79f2957e2c94e44786f6ca3dfc7384aaceb80c0a",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/jobs.py",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/jobs.py?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/79f2957e2c94e44786f6ca3dfc7384aaceb80c0a",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/jobs.py"
+ }
+ },
+ {
+ "name": "magic",
+ "path": "magic",
+ "sha": "6342094c1d4b1af948867ffba67cf0b866e5613c",
+ "size": 659195,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/magic?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/magic",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/6342094c1d4b1af948867ffba67cf0b866e5613c",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/magic",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/magic?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/6342094c1d4b1af948867ffba67cf0b866e5613c",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/magic"
+ }
+ },
+ {
+ "name": "manage.py",
+ "path": "manage.py",
+ "sha": "a0b80d4c7b5fd7e50d6dcb5bcbdcd995b8da27f0",
+ "size": 15323,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/manage.py?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/manage.py",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/a0b80d4c7b5fd7e50d6dcb5bcbdcd995b8da27f0",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/manage.py",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/manage.py?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/a0b80d4c7b5fd7e50d6dcb5bcbdcd995b8da27f0",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/manage.py"
+ }
+ },
+ {
+ "name": "migrations",
+ "path": "migrations",
+ "sha": "da206a9809330d01f4800718bca2a20c05038b44",
+ "size": 0,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/migrations?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/migrations",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/da206a9809330d01f4800718bca2a20c05038b44",
+ "download_url": null,
+ "type": "dir",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/migrations?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/da206a9809330d01f4800718bca2a20c05038b44",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/migrations"
+ }
+ },
+ {
+ "name": "requirements.in",
+ "path": "requirements.in",
+ "sha": "88b4e0a1c8093fae2b4fa52534035f9f85ed0956",
+ "size": 2433,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/requirements.in?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/requirements.in",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/88b4e0a1c8093fae2b4fa52534035f9f85ed0956",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/requirements.in",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/requirements.in?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/88b4e0a1c8093fae2b4fa52534035f9f85ed0956",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/requirements.in"
+ }
+ },
+ {
+ "name": "tests",
+ "path": "tests",
+ "sha": "88b4e0a1c8093fae2b4fa52534035f9f85ed0956",
+ "size": 0,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/tests?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/tests",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/88b4e0a1c8093fae2b4fa52534035f9f85ed0956",
+ "download_url": null,
+ "type": "dir",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/tests?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/88b4e0a1c8093fae2b4fa52534035f9f85ed0956",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/tests"
+ }
+ },
+ {
+ "name": "todo.txt",
+ "path": "todo.txt",
+ "sha": "3e369beef1c9e64f0c10735d35aa8ad755daddc6",
+ "size": 1147,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/todo.txt?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/todo.txt",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/3e369beef1c9e64f0c10735d35aa8ad755daddc6",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/todo.txt",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/todo.txt?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/3e369beef1c9e64f0c10735d35aa8ad755daddc6",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/todo.txt"
+ }
+ },
+ {
+ "name": "update_definitions.sh",
+ "path": "update_definitions.sh",
+ "sha": "fbde266ea5ebd519b94d18f8f78ab825b02766df",
+ "size": 7877,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/update_definitions.sh?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/update_definitions.sh",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/fbde266ea5ebd519b94d18f8f78ab825b02766df",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/update_definitions.sh",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/update_definitions.sh?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/fbde266ea5ebd519b94d18f8f78ab825b02766df",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/update_definitions.sh"
+ }
+ }
+]
diff --git a/uv/spec/fixtures/github/contents_python_only_setup.json b/uv/spec/fixtures/github/contents_python_only_setup.json
new file mode 100644
index 00000000000..a3efcdbe512
--- /dev/null
+++ b/uv/spec/fixtures/github/contents_python_only_setup.json
@@ -0,0 +1,418 @@
+[
+ {
+ "name": ".codeclimate.yml",
+ "path": ".codeclimate.yml",
+ "sha": "6393602fac96cfe31d64f89476014124b4a13b85",
+ "size": 416,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.codeclimate.yml?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.codeclimate.yml",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/6393602fac96cfe31d64f89476014124b4a13b85",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/.codeclimate.yml",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.codeclimate.yml?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/6393602fac96cfe31d64f89476014124b4a13b85",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.codeclimate.yml"
+ }
+ },
+ {
+ "name": ".coveragerc",
+ "path": ".coveragerc",
+ "sha": "be7fdc86067d0924f3e1e92c1a3ed92d9486fcbb",
+ "size": 646,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.coveragerc?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.coveragerc",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/be7fdc86067d0924f3e1e92c1a3ed92d9486fcbb",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/.coveragerc",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.coveragerc?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/be7fdc86067d0924f3e1e92c1a3ed92d9486fcbb",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.coveragerc"
+ }
+ },
+ {
+ "name": ".csslintrc",
+ "path": ".csslintrc",
+ "sha": "aacba956e5bbede1c195ce554fcad3e200b24ff8",
+ "size": 107,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.csslintrc?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.csslintrc",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/aacba956e5bbede1c195ce554fcad3e200b24ff8",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/.csslintrc",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.csslintrc?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/aacba956e5bbede1c195ce554fcad3e200b24ff8",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.csslintrc"
+ }
+ },
+ {
+ "name": ".env.example",
+ "path": ".env.example",
+ "sha": "d9f599b33ecd834ea88979dcc3daf4fcafacf4e7",
+ "size": 2617,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.env.example?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.env.example",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/d9f599b33ecd834ea88979dcc3daf4fcafacf4e7",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/.env.example",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.env.example?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/d9f599b33ecd834ea88979dcc3daf4fcafacf4e7",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.env.example"
+ }
+ },
+ {
+ "name": ".eslintignore",
+ "path": ".eslintignore",
+ "sha": "96212a3593bac8c93f624b77185a8d11018efd96",
+ "size": 16,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.eslintignore?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.eslintignore",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/96212a3593bac8c93f624b77185a8d11018efd96",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/.eslintignore",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.eslintignore?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/96212a3593bac8c93f624b77185a8d11018efd96",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.eslintignore"
+ }
+ },
+ {
+ "name": ".eslintrc.yml",
+ "path": ".eslintrc.yml",
+ "sha": "a6a0ce9c44238e06ff55ca335a66a4e16810da38",
+ "size": 6056,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.eslintrc.yml?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.eslintrc.yml",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/a6a0ce9c44238e06ff55ca335a66a4e16810da38",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/.eslintrc.yml",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.eslintrc.yml?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/a6a0ce9c44238e06ff55ca335a66a4e16810da38",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.eslintrc.yml"
+ }
+ },
+ {
+ "name": ".gitignore",
+ "path": ".gitignore",
+ "sha": "93923ac3a463bd17d0aefca2de9d2810f243d747",
+ "size": 1073,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.gitignore?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.gitignore",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/93923ac3a463bd17d0aefca2de9d2810f243d747",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/.gitignore",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.gitignore?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/93923ac3a463bd17d0aefca2de9d2810f243d747",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.gitignore"
+ }
+ },
+ {
+ "name": "LICENSE.md",
+ "path": "LICENSE.md",
+ "sha": "8dada3edaf50dbc082c9a125058f25def75e625a",
+ "size": 11357,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/LICENSE.md?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/LICENSE.md",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/8dada3edaf50dbc082c9a125058f25def75e625a",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/LICENSE.md",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/LICENSE.md?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/8dada3edaf50dbc082c9a125058f25def75e625a",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/LICENSE.md"
+ }
+ },
+ {
+ "name": "Procfile",
+ "path": "Procfile",
+ "sha": "72e4ef1be7c64eb0f874344bc8a6cf859bd39e00",
+ "size": 26,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/Procfile?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/Procfile",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/72e4ef1be7c64eb0f874344bc8a6cf859bd39e00",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/Procfile",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/Procfile?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/72e4ef1be7c64eb0f874344bc8a6cf859bd39e00",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/Procfile"
+ }
+ },
+ {
+ "name": "README.md",
+ "path": "README.md",
+ "sha": "01aae7d562fe164d2cee644e8ef5fba82d2b8e81",
+ "size": 1589,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/README.md?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/README.md",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/01aae7d562fe164d2cee644e8ef5fba82d2b8e81",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/README.md",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/README.md?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/01aae7d562fe164d2cee644e8ef5fba82d2b8e81",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/README.md"
+ }
+ },
+ {
+ "name": "Vagrantfile.example",
+ "path": "Vagrantfile.example",
+ "sha": "54be29ea9e1e2ecdbfa642656cded8b3cb85c910",
+ "size": 4329,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/Vagrantfile.example?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/Vagrantfile.example",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/54be29ea9e1e2ecdbfa642656cded8b3cb85c910",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/Vagrantfile.example",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/Vagrantfile.example?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/54be29ea9e1e2ecdbfa642656cded8b3cb85c910",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/Vagrantfile.example"
+ }
+ },
+ {
+ "name": "app",
+ "path": "app",
+ "sha": "f9e84e24364972f3aa4f92b869a622db1f260fa1",
+ "size": 0,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/app?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/app",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/f9e84e24364972f3aa4f92b869a622db1f260fa1",
+ "download_url": null,
+ "type": "dir",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/app?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/f9e84e24364972f3aa4f92b869a622db1f260fa1",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/app"
+ }
+ },
+ {
+ "name": "build_scripts",
+ "path": "build_scripts",
+ "sha": "be8e80f054e47f0c9a6fc9cfe5061346c6f8b2d0",
+ "size": 0,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/build_scripts?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/build_scripts",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/be8e80f054e47f0c9a6fc9cfe5061346c6f8b2d0",
+ "download_url": null,
+ "type": "dir",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/build_scripts?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/be8e80f054e47f0c9a6fc9cfe5061346c6f8b2d0",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/build_scripts"
+ }
+ },
+ {
+ "name": "celery_worker.py",
+ "path": "celery_worker.py",
+ "sha": "c84c73c1f1c1aa42550a08ae4f32dc955ced5f18",
+ "size": 279,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/celery_worker.py?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/celery_worker.py",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/c84c73c1f1c1aa42550a08ae4f32dc955ced5f18",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/celery_worker.py",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/celery_worker.py?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/c84c73c1f1c1aa42550a08ae4f32dc955ced5f18",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/celery_worker.py"
+ }
+ },
+ {
+ "name": "config.py",
+ "path": "config.py",
+ "sha": "2886556fc4844e708472a99a85b42b4f5b51d509",
+ "size": 8250,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/config.py?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/config.py",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/2886556fc4844e708472a99a85b42b4f5b51d509",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/config.py",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/config.py?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/2886556fc4844e708472a99a85b42b4f5b51d509",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/config.py"
+ }
+ },
+ {
+ "name": "crontab",
+ "path": "crontab",
+ "sha": "1e2c1da613e8272df6ece759565524c93bc76780",
+ "size": 300,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/crontab?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/crontab",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/1e2c1da613e8272df6ece759565524c93bc76780",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/crontab",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/crontab?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/1e2c1da613e8272df6ece759565524c93bc76780",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/crontab"
+ }
+ },
+ {
+ "name": "data",
+ "path": "data",
+ "sha": "7bceca86ff0e88cb53c8828d441f5e0725776395",
+ "size": 0,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/data?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/data",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/7bceca86ff0e88cb53c8828d441f5e0725776395",
+ "download_url": null,
+ "type": "dir",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/data?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/7bceca86ff0e88cb53c8828d441f5e0725776395",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/data"
+ }
+ },
+ {
+ "name": "gunicorn_config.py",
+ "path": "gunicorn_config.py",
+ "sha": "7b1a455133c2e78611550e45e8d2072d5c5c4ad7",
+ "size": 2504,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/gunicorn_config.py?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/gunicorn_config.py",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/7b1a455133c2e78611550e45e8d2072d5c5c4ad7",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/gunicorn_config.py",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/gunicorn_config.py?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/7b1a455133c2e78611550e45e8d2072d5c5c4ad7",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/gunicorn_config.py"
+ }
+ },
+ {
+ "name": "jobs.py",
+ "path": "jobs.py",
+ "sha": "79f2957e2c94e44786f6ca3dfc7384aaceb80c0a",
+ "size": 6213,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/jobs.py?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/jobs.py",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/79f2957e2c94e44786f6ca3dfc7384aaceb80c0a",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/jobs.py",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/jobs.py?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/79f2957e2c94e44786f6ca3dfc7384aaceb80c0a",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/jobs.py"
+ }
+ },
+ {
+ "name": "magic",
+ "path": "magic",
+ "sha": "6342094c1d4b1af948867ffba67cf0b866e5613c",
+ "size": 659195,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/magic?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/magic",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/6342094c1d4b1af948867ffba67cf0b866e5613c",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/magic",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/magic?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/6342094c1d4b1af948867ffba67cf0b866e5613c",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/magic"
+ }
+ },
+ {
+ "name": "manage.py",
+ "path": "manage.py",
+ "sha": "a0b80d4c7b5fd7e50d6dcb5bcbdcd995b8da27f0",
+ "size": 15323,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/manage.py?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/manage.py",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/a0b80d4c7b5fd7e50d6dcb5bcbdcd995b8da27f0",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/manage.py",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/manage.py?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/a0b80d4c7b5fd7e50d6dcb5bcbdcd995b8da27f0",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/manage.py"
+ }
+ },
+ {
+ "name": "migrations",
+ "path": "migrations",
+ "sha": "da206a9809330d01f4800718bca2a20c05038b44",
+ "size": 0,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/migrations?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/migrations",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/da206a9809330d01f4800718bca2a20c05038b44",
+ "download_url": null,
+ "type": "dir",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/migrations?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/da206a9809330d01f4800718bca2a20c05038b44",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/migrations"
+ }
+ },
+ {
+ "name": "setup.py",
+ "path": "setup.py",
+ "sha": "88b4e0a1c8093fae2b4fa52534035f9f85ed0956",
+ "size": 2433,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/setup.py?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/setup.py",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/88b4e0a1c8093fae2b4fa52534035f9f85ed0956",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/setup.py",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/setup.py?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/88b4e0a1c8093fae2b4fa52534035f9f85ed0956",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/setup.py"
+ }
+ },
+ {
+ "name": "tests",
+ "path": "tests",
+ "sha": "88b4e0a1c8093fae2b4fa52534035f9f85ed0956",
+ "size": 0,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/tests?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/tests",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/88b4e0a1c8093fae2b4fa52534035f9f85ed0956",
+ "download_url": null,
+ "type": "dir",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/tests?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/88b4e0a1c8093fae2b4fa52534035f9f85ed0956",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/tests"
+ }
+ },
+ {
+ "name": "todo.txt",
+ "path": "todo.txt",
+ "sha": "3e369beef1c9e64f0c10735d35aa8ad755daddc6",
+ "size": 1147,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/todo.txt?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/todo.txt",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/3e369beef1c9e64f0c10735d35aa8ad755daddc6",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/todo.txt",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/todo.txt?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/3e369beef1c9e64f0c10735d35aa8ad755daddc6",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/todo.txt"
+ }
+ },
+ {
+ "name": "update_definitions.sh",
+ "path": "update_definitions.sh",
+ "sha": "fbde266ea5ebd519b94d18f8f78ab825b02766df",
+ "size": 7877,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/update_definitions.sh?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/update_definitions.sh",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/fbde266ea5ebd519b94d18f8f78ab825b02766df",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/update_definitions.sh",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/update_definitions.sh?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/fbde266ea5ebd519b94d18f8f78ab825b02766df",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/update_definitions.sh"
+ }
+ }
+]
diff --git a/uv/spec/fixtures/github/contents_python_only_setup_cfg.json b/uv/spec/fixtures/github/contents_python_only_setup_cfg.json
new file mode 100644
index 00000000000..4fed78216f7
--- /dev/null
+++ b/uv/spec/fixtures/github/contents_python_only_setup_cfg.json
@@ -0,0 +1,418 @@
+[
+ {
+ "name": ".codeclimate.yml",
+ "path": ".codeclimate.yml",
+ "sha": "6393602fac96cfe31d64f89476014124b4a13b85",
+ "size": 416,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.codeclimate.yml?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.codeclimate.yml",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/6393602fac96cfe31d64f89476014124b4a13b85",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/.codeclimate.yml",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.codeclimate.yml?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/6393602fac96cfe31d64f89476014124b4a13b85",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.codeclimate.yml"
+ }
+ },
+ {
+ "name": ".coveragerc",
+ "path": ".coveragerc",
+ "sha": "be7fdc86067d0924f3e1e92c1a3ed92d9486fcbb",
+ "size": 646,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.coveragerc?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.coveragerc",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/be7fdc86067d0924f3e1e92c1a3ed92d9486fcbb",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/.coveragerc",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.coveragerc?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/be7fdc86067d0924f3e1e92c1a3ed92d9486fcbb",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.coveragerc"
+ }
+ },
+ {
+ "name": ".csslintrc",
+ "path": ".csslintrc",
+ "sha": "aacba956e5bbede1c195ce554fcad3e200b24ff8",
+ "size": 107,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.csslintrc?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.csslintrc",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/aacba956e5bbede1c195ce554fcad3e200b24ff8",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/.csslintrc",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.csslintrc?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/aacba956e5bbede1c195ce554fcad3e200b24ff8",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.csslintrc"
+ }
+ },
+ {
+ "name": ".env.example",
+ "path": ".env.example",
+ "sha": "d9f599b33ecd834ea88979dcc3daf4fcafacf4e7",
+ "size": 2617,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.env.example?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.env.example",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/d9f599b33ecd834ea88979dcc3daf4fcafacf4e7",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/.env.example",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.env.example?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/d9f599b33ecd834ea88979dcc3daf4fcafacf4e7",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.env.example"
+ }
+ },
+ {
+ "name": ".eslintignore",
+ "path": ".eslintignore",
+ "sha": "96212a3593bac8c93f624b77185a8d11018efd96",
+ "size": 16,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.eslintignore?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.eslintignore",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/96212a3593bac8c93f624b77185a8d11018efd96",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/.eslintignore",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.eslintignore?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/96212a3593bac8c93f624b77185a8d11018efd96",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.eslintignore"
+ }
+ },
+ {
+ "name": ".eslintrc.yml",
+ "path": ".eslintrc.yml",
+ "sha": "a6a0ce9c44238e06ff55ca335a66a4e16810da38",
+ "size": 6056,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.eslintrc.yml?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.eslintrc.yml",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/a6a0ce9c44238e06ff55ca335a66a4e16810da38",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/.eslintrc.yml",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.eslintrc.yml?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/a6a0ce9c44238e06ff55ca335a66a4e16810da38",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.eslintrc.yml"
+ }
+ },
+ {
+ "name": ".gitignore",
+ "path": ".gitignore",
+ "sha": "93923ac3a463bd17d0aefca2de9d2810f243d747",
+ "size": 1073,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.gitignore?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.gitignore",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/93923ac3a463bd17d0aefca2de9d2810f243d747",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/.gitignore",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.gitignore?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/93923ac3a463bd17d0aefca2de9d2810f243d747",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.gitignore"
+ }
+ },
+ {
+ "name": "LICENSE.md",
+ "path": "LICENSE.md",
+ "sha": "8dada3edaf50dbc082c9a125058f25def75e625a",
+ "size": 11357,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/LICENSE.md?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/LICENSE.md",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/8dada3edaf50dbc082c9a125058f25def75e625a",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/LICENSE.md",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/LICENSE.md?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/8dada3edaf50dbc082c9a125058f25def75e625a",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/LICENSE.md"
+ }
+ },
+ {
+ "name": "Procfile",
+ "path": "Procfile",
+ "sha": "72e4ef1be7c64eb0f874344bc8a6cf859bd39e00",
+ "size": 26,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/Procfile?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/Procfile",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/72e4ef1be7c64eb0f874344bc8a6cf859bd39e00",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/Procfile",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/Procfile?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/72e4ef1be7c64eb0f874344bc8a6cf859bd39e00",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/Procfile"
+ }
+ },
+ {
+ "name": "README.md",
+ "path": "README.md",
+ "sha": "01aae7d562fe164d2cee644e8ef5fba82d2b8e81",
+ "size": 1589,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/README.md?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/README.md",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/01aae7d562fe164d2cee644e8ef5fba82d2b8e81",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/README.md",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/README.md?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/01aae7d562fe164d2cee644e8ef5fba82d2b8e81",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/README.md"
+ }
+ },
+ {
+ "name": "Vagrantfile.example",
+ "path": "Vagrantfile.example",
+ "sha": "54be29ea9e1e2ecdbfa642656cded8b3cb85c910",
+ "size": 4329,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/Vagrantfile.example?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/Vagrantfile.example",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/54be29ea9e1e2ecdbfa642656cded8b3cb85c910",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/Vagrantfile.example",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/Vagrantfile.example?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/54be29ea9e1e2ecdbfa642656cded8b3cb85c910",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/Vagrantfile.example"
+ }
+ },
+ {
+ "name": "app",
+ "path": "app",
+ "sha": "f9e84e24364972f3aa4f92b869a622db1f260fa1",
+ "size": 0,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/app?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/app",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/f9e84e24364972f3aa4f92b869a622db1f260fa1",
+ "download_url": null,
+ "type": "dir",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/app?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/f9e84e24364972f3aa4f92b869a622db1f260fa1",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/app"
+ }
+ },
+ {
+ "name": "build_scripts",
+ "path": "build_scripts",
+ "sha": "be8e80f054e47f0c9a6fc9cfe5061346c6f8b2d0",
+ "size": 0,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/build_scripts?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/build_scripts",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/be8e80f054e47f0c9a6fc9cfe5061346c6f8b2d0",
+ "download_url": null,
+ "type": "dir",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/build_scripts?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/be8e80f054e47f0c9a6fc9cfe5061346c6f8b2d0",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/build_scripts"
+ }
+ },
+ {
+ "name": "celery_worker.py",
+ "path": "celery_worker.py",
+ "sha": "c84c73c1f1c1aa42550a08ae4f32dc955ced5f18",
+ "size": 279,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/celery_worker.py?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/celery_worker.py",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/c84c73c1f1c1aa42550a08ae4f32dc955ced5f18",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/celery_worker.py",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/celery_worker.py?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/c84c73c1f1c1aa42550a08ae4f32dc955ced5f18",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/celery_worker.py"
+ }
+ },
+ {
+ "name": "config.py",
+ "path": "config.py",
+ "sha": "2886556fc4844e708472a99a85b42b4f5b51d509",
+ "size": 8250,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/config.py?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/config.py",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/2886556fc4844e708472a99a85b42b4f5b51d509",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/config.py",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/config.py?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/2886556fc4844e708472a99a85b42b4f5b51d509",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/config.py"
+ }
+ },
+ {
+ "name": "crontab",
+ "path": "crontab",
+ "sha": "1e2c1da613e8272df6ece759565524c93bc76780",
+ "size": 300,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/crontab?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/crontab",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/1e2c1da613e8272df6ece759565524c93bc76780",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/crontab",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/crontab?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/1e2c1da613e8272df6ece759565524c93bc76780",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/crontab"
+ }
+ },
+ {
+ "name": "data",
+ "path": "data",
+ "sha": "7bceca86ff0e88cb53c8828d441f5e0725776395",
+ "size": 0,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/data?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/data",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/7bceca86ff0e88cb53c8828d441f5e0725776395",
+ "download_url": null,
+ "type": "dir",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/data?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/7bceca86ff0e88cb53c8828d441f5e0725776395",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/data"
+ }
+ },
+ {
+ "name": "gunicorn_config.py",
+ "path": "gunicorn_config.py",
+ "sha": "7b1a455133c2e78611550e45e8d2072d5c5c4ad7",
+ "size": 2504,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/gunicorn_config.py?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/gunicorn_config.py",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/7b1a455133c2e78611550e45e8d2072d5c5c4ad7",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/gunicorn_config.py",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/gunicorn_config.py?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/7b1a455133c2e78611550e45e8d2072d5c5c4ad7",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/gunicorn_config.py"
+ }
+ },
+ {
+ "name": "jobs.py",
+ "path": "jobs.py",
+ "sha": "79f2957e2c94e44786f6ca3dfc7384aaceb80c0a",
+ "size": 6213,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/jobs.py?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/jobs.py",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/79f2957e2c94e44786f6ca3dfc7384aaceb80c0a",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/jobs.py",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/jobs.py?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/79f2957e2c94e44786f6ca3dfc7384aaceb80c0a",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/jobs.py"
+ }
+ },
+ {
+ "name": "magic",
+ "path": "magic",
+ "sha": "6342094c1d4b1af948867ffba67cf0b866e5613c",
+ "size": 659195,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/magic?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/magic",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/6342094c1d4b1af948867ffba67cf0b866e5613c",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/magic",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/magic?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/6342094c1d4b1af948867ffba67cf0b866e5613c",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/magic"
+ }
+ },
+ {
+ "name": "manage.py",
+ "path": "manage.py",
+ "sha": "a0b80d4c7b5fd7e50d6dcb5bcbdcd995b8da27f0",
+ "size": 15323,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/manage.py?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/manage.py",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/a0b80d4c7b5fd7e50d6dcb5bcbdcd995b8da27f0",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/manage.py",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/manage.py?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/a0b80d4c7b5fd7e50d6dcb5bcbdcd995b8da27f0",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/manage.py"
+ }
+ },
+ {
+ "name": "migrations",
+ "path": "migrations",
+ "sha": "da206a9809330d01f4800718bca2a20c05038b44",
+ "size": 0,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/migrations?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/migrations",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/da206a9809330d01f4800718bca2a20c05038b44",
+ "download_url": null,
+ "type": "dir",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/migrations?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/da206a9809330d01f4800718bca2a20c05038b44",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/migrations"
+ }
+ },
+ {
+ "name": "setup.cfg",
+ "path": "setup.cfg",
+ "sha": "88b4e0a1c8093fae2b4fa52534035f9f85ed0956",
+ "size": 2433,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/setup.cfg?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/setup.cfg",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/88b4e0a1c8093fae2b4fa52534035f9f85ed0956",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/setup.cfg",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/setup.cfg?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/88b4e0a1c8093fae2b4fa52534035f9f85ed0956",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/setup.cfg"
+ }
+ },
+ {
+ "name": "tests",
+ "path": "tests",
+ "sha": "88b4e0a1c8093fae2b4fa52534035f9f85ed0956",
+ "size": 0,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/tests?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/tests",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/88b4e0a1c8093fae2b4fa52534035f9f85ed0956",
+ "download_url": null,
+ "type": "dir",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/tests?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/88b4e0a1c8093fae2b4fa52534035f9f85ed0956",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/tests"
+ }
+ },
+ {
+ "name": "todo.txt",
+ "path": "todo.txt",
+ "sha": "3e369beef1c9e64f0c10735d35aa8ad755daddc6",
+ "size": 1147,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/todo.txt?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/todo.txt",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/3e369beef1c9e64f0c10735d35aa8ad755daddc6",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/todo.txt",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/todo.txt?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/3e369beef1c9e64f0c10735d35aa8ad755daddc6",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/todo.txt"
+ }
+ },
+ {
+ "name": "update_definitions.sh",
+ "path": "update_definitions.sh",
+ "sha": "fbde266ea5ebd519b94d18f8f78ab825b02766df",
+ "size": 7877,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/update_definitions.sh?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/update_definitions.sh",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/fbde266ea5ebd519b94d18f8f78ab825b02766df",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/update_definitions.sh",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/update_definitions.sh?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/fbde266ea5ebd519b94d18f8f78ab825b02766df",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/update_definitions.sh"
+ }
+ }
+]
diff --git a/uv/spec/fixtures/github/contents_python_pdm_lock.json b/uv/spec/fixtures/github/contents_python_pdm_lock.json
new file mode 100644
index 00000000000..4b0581a21f2
--- /dev/null
+++ b/uv/spec/fixtures/github/contents_python_pdm_lock.json
@@ -0,0 +1,18 @@
+{
+ "name": "pdm.lock",
+ "path": "pdm.lock",
+ "sha": "31a43a994d33ec6fab0a26a08b7313c6836e0822",
+ "size": 3281,
+ "url": "https://api.github.com/repos/pdm-project/setup-pdm/contents/pdm.lock?ref=main",
+ "html_url": "https://github.com/pdm-project/setup-pdm/blob/main/pdm.lock",
+ "git_url": "https://api.github.com/repos/pdm-project/setup-pdm/git/blobs/31a43a994d33ec6fab0a26a08b7313c6836e0822",
+ "download_url": "https://raw.githubusercontent.com/pdm-project/setup-pdm/main/pdm.lock",
+ "type": "file",
+ "content": "W1twYWNrYWdlXV0KbmFtZSA9ICJjZXJ0aWZpIgp2ZXJzaW9uID0gIjIwMjIu\nNi4xNSIKcmVxdWlyZXNfcHl0aG9uID0gIj49My42IgpzdW1tYXJ5ID0gIlB5\ndGhvbiBwYWNrYWdlIGZvciBwcm92aWRpbmcgTW96aWxsYSdzIENBIEJ1bmRs\nZS4iCgpbW3BhY2thZ2VdXQpuYW1lID0gImNoYXJkZXQiCnZlcnNpb24gPSAi\nNS4wLjAiCnJlcXVpcmVzX3B5dGhvbiA9ICI+PTMuNiIKc3VtbWFyeSA9ICJV\nbml2ZXJzYWwgZW5jb2RpbmcgZGV0ZWN0b3IgZm9yIFB5dGhvbiAzIgoKW1tw\nYWNrYWdlXV0KbmFtZSA9ICJpZG5hIgp2ZXJzaW9uID0gIjMuMyIKcmVxdWly\nZXNfcHl0aG9uID0gIj49My41IgpzdW1tYXJ5ID0gIkludGVybmF0aW9uYWxp\nemVkIERvbWFpbiBOYW1lcyBpbiBBcHBsaWNhdGlvbnMgKElETkEpIgoKW1tw\nYWNrYWdlXV0KbmFtZSA9ICJweXR6Igp2ZXJzaW9uID0gIjIwMjIuMSIKc3Vt\nbWFyeSA9ICJXb3JsZCB0aW1lem9uZSBkZWZpbml0aW9ucywgbW9kZXJuIGFu\nZCBoaXN0b3JpY2FsIgoKW1twYWNrYWdlXV0KbmFtZSA9ICJ1cmxsaWIzIgp2\nZXJzaW9uID0gIjEuMjYuMTAiCnJlcXVpcmVzX3B5dGhvbiA9ICI+PTIuNywg\nIT0zLjAuKiwgIT0zLjEuKiwgIT0zLjIuKiwgIT0zLjMuKiwgIT0zLjQuKiwg\nIT0zLjUuKiwgPDQiCnN1bW1hcnkgPSAiSFRUUCBsaWJyYXJ5IHdpdGggdGhy\nZWFkLXNhZmUgY29ubmVjdGlvbiBwb29saW5nLCBmaWxlIHBvc3QsIGFuZCBt\nb3JlLiIKClttZXRhZGF0YV0KbG9ja192ZXJzaW9uID0gIjQuMCIKY29udGVu\ndF9oYXNoID0gInNoYTI1Njo5Mzg2YjNkNmFjOTU5NTA4ZWYzY2Y3NWZkYWI3\nYzgyYmQ0NDBjMGE3OTg0MWEwNzg2ZDcxYzFlNDJhNThiMjRkIgoKW21ldGFk\nYXRhLmZpbGVzXQoiY2VydGlmaSAyMDIyLjYuMTUiID0gWwogICAge3VybCA9\nICJodHRwczovL2ZpbGVzLnB5dGhvbmhvc3RlZC5vcmcvcGFja2FnZXMvZTkv\nMDYvZDNkMzY3YjdhZjYzMDViMTZmMGQyOGFlMmFhZWI4NjE1NGZhOTFmMTQ0\nZjAzNmMyZDUwMDJhNWEyMDJiL2NlcnRpZmktMjAyMi42LjE1LXB5My1ub25l\nLWFueS53aGwiLCBoYXNoID0gInNoYTI1NjpmZTg2NDE1ZDU1ZTg0NzE5ZDc1\nZjhiNjk0MTRmNjQzOGFjMzU0N2QyMDc4YWI5MWI2N2U3NzllZjY5Mzc4NDEy\nIn0sCiAgICB7dXJsID0gImh0dHBzOi8vZmlsZXMucHl0aG9uaG9zdGVkLm9y\nZy9wYWNrYWdlcy9jYy84NS8zMTlhOGE2ODRlOGFjNmQ4N2ExMTkzMDkwZTA2\nYjZiYmIzMDI3MTc0OTYzODBlMjI1ZWUxMDQ4N2M4ODgvY2VydGlmaS0yMDIy\nLjYuMTUudGFyLmd6IiwgaGFzaCA9ICJzaGEyNTY6ODRjODVhOTA3OGIxMTEw\nNWYwNGYzMDM2YTk0ODJhZTEwZTQ2MjE2MTZkYjMxM2ZlMDQ1ZGQyNDc0M2Ew\nODIwZCJ9LApdCiJjaGFyZGV0IDUuMC4wIiA9IFsKICAgIHt1cmwgPSAiaHR0\ncHM6Ly9maWxlcy5weXRob25ob3N0ZWQub3JnL3BhY2thZ2VzLzRjL2QxLzFi\nOTZkZDY5ZmE0MmYyMGI3MDcwMWI1Y2Q0MmE3NWRkNWYwYzdhMjRkYzBhYmZl\nZjM1Y2MxNDYyMTBkYy9jaGFyZGV0LTUuMC4wLXB5My1ub25lLWFueS53aGwi\nLCBoYXNoID0gInNoYTI1NjpkM2U2NGYwMjJkMjU0MTgzMDAxZWNjYzVkYjQw\nNDA1MjBjMGYyM2IxYTNmMzNkNjQxM2UwOTllYjdmMTI2NTU3In0sCiAgICB7\ndXJsID0gImh0dHBzOi8vZmlsZXMucHl0aG9uaG9zdGVkLm9yZy9wYWNrYWdl\ncy8zMS9hMi8xMmMwOTA3MTNiM2QwZTE0MWYzNjcyMzZkM2E4YmRjM2U1ZmNh\nMGQ4M2ZmMzY0N2FmNDg5MmMxNmMyMDUvY2hhcmRldC01LjAuMC50YXIuZ3oi\nLCBoYXNoID0gInNoYTI1NjowMzY4ZGYyYmZkNzhiNWZjMjA1NzJiYjRlOWJi\nN2ZiNTNlMmMwOTRmNjBhZTk5OTMzMzllODY3MWQwYWZiOGFhIn0sCl0KImlk\nbmEgMy4zIiA9IFsKICAgIHt1cmwgPSAiaHR0cHM6Ly9maWxlcy5weXRob25o\nb3N0ZWQub3JnL3BhY2thZ2VzLzA0L2EyL2Q5MThkY2QyMjM1NGQ4OTU4ZmUx\nMTNlMWEzNjMwMTM3ZTBmYzhiNDQ4NTlhZGUzMDYzOTgyZWFjZDJhNC9pZG5h\nLTMuMy1weTMtbm9uZS1hbnkud2hsIiwgaGFzaCA9ICJzaGEyNTY6ODRkOWRk\nMDQ3ZmZhODA1OTZlMGYyNDZlMmVhYjBiMzkxNzg4YjA1MDM1ODRlODk0NWYy\nMzY4MjU2ZDI3MzVmZiJ9LAogICAge3VybCA9ICJodHRwczovL2ZpbGVzLnB5\ndGhvbmhvc3RlZC5vcmcvcGFja2FnZXMvNjIvMDgvZTNmYzdjODE2MTA5MGY3\nNDJmNTA0ZjQwYjFiY2NiZmM1NDRkNGE0ZTA5ZWI3NzRiZjQwYWFmY2U1NDM2\nL2lkbmEtMy4zLnRhci5neiIsIGhhc2ggPSAic2hhMjU2OjlkNjQzZmYwYTU1\nYjc2MmQ1Y2RiMTI0YjhlYWE5OWM2NjMyMmUyMTU3YjY5MTYwYmMzMjc5NmU4\nMjQzNjBlNmQifSwKXQoicHl0eiAyMDIyLjEiID0gWwogICAge3VybCA9ICJo\ndHRwczovL2ZpbGVzLnB5dGhvbmhvc3RlZC5vcmcvcGFja2FnZXMvNjAvMmUv\nZGVjMWNjMThjNTFiOGRmMzNjN2M0ZDBhMzIxYjA4NGNmMzhlMTczM2I5OGY5\nZDE1MDE4ODgwZmI0OTcwL3B5dHotMjAyMi4xLXB5Mi5weTMtbm9uZS1hbnku\nd2hsIiwgaGFzaCA9ICJzaGEyNTY6ZTY4OTg1OTg1Mjk2ZDlhNjZhODgxZWIz\nMTkzYjA5MDYyNDYyNDUyOTRhODgxZTdjOGFmZTYyMzg2NmFjNmE1YyJ9LAog\nICAge3VybCA9ICJodHRwczovL2ZpbGVzLnB5dGhvbmhvc3RlZC5vcmcvcGFj\na2FnZXMvMmYvNWYvYTBmNjUzMzExYWRmZjkwNWJiY2FhNmQzZGZhZjk3ZWRj\nZjRkMjYxMzgzOTNjNmNjZDM3YTQ4NDg1MWZiL3B5dHotMjAyMi4xLnRhci5n\neiIsIGhhc2ggPSAic2hhMjU2OjFlNzYwZTJmZTZhODE2M2JjMGIzZDlhMTlj\nNGY4NDM0MmFmYTBhMmFmZmViZmFhODRiMDFiOTc4YTAyZWNhYTcifSwKXQoi\ndXJsbGliMyAxLjI2LjEwIiA9IFsKICAgIHt1cmwgPSAiaHR0cHM6Ly9maWxl\ncy5weXRob25ob3N0ZWQub3JnL3BhY2thZ2VzLzY4LzQ3LzkzZDNkMjhlOTdj\nNzU3N2Y1NjM5MDM5MDc5MTJmNGIzODA0MDU0ZTQ4NzdhNWJhNjY1MWY3MTgy\nYzUzYi91cmxsaWIzLTEuMjYuMTAtcHkyLnB5My1ub25lLWFueS53aGwiLCBo\nYXNoID0gInNoYTI1Njo4Mjk4ZDZkNTZkMzliZTBlM2JjMTNjMWM5N2QxMzNm\nOWI0NWQ3OTcxNjlhMGUxMWNkZDBlMDQ4OWQ3ODZmN2VjIn0sCiAgICB7dXJs\nID0gImh0dHBzOi8vZmlsZXMucHl0aG9uaG9zdGVkLm9yZy9wYWNrYWdlcy8y\nNS8zNi9mMDU2ZTVmMTM4OTAwNGNmODg2YmI3YTg1MTQwNzdmMjQyMjQyMzhh\nNzUzNDQ5N2MwMTRhNmI5YWM3NzAvdXJsbGliMy0xLjI2LjEwLnRhci5neiIs\nIGhhc2ggPSAic2hhMjU2Ojg3OWJhNGQxZTg5NjU0ZDk3NjljZTEzMTIxZTBm\nOTQzMTBlYTMyZThkMmY4Y2Y1ODdiNzdjMDhiYmNkYjMwZDYifSwKXQo=\n",
+ "encoding": "base64",
+ "_links": {
+ "self": "https://api.github.com/repos/pdm-project/setup-pdm/contents/pdm.lock?ref=main",
+ "git": "https://api.github.com/repos/pdm-project/setup-pdm/git/blobs/31a43a994d33ec6fab0a26a08b7313c6836e0822",
+ "html": "https://github.com/pdm-project/setup-pdm/blob/main/pdm.lock"
+ }
+}
diff --git a/uv/spec/fixtures/github/contents_python_pipfile.json b/uv/spec/fixtures/github/contents_python_pipfile.json
new file mode 100644
index 00000000000..387a780dfa8
--- /dev/null
+++ b/uv/spec/fixtures/github/contents_python_pipfile.json
@@ -0,0 +1,18 @@
+{
+ "name": "Pipfile",
+ "path": "Pipfile",
+ "sha": "11fc8c6d445a2302417c65b86fb771243a3a90b7",
+ "size": 541,
+ "url": "https://api.github.com/repos/mozilla/mozillians-tests/contents/Pipfile?ref=master",
+ "html_url": "https://github.com/mozilla/mozillians-tests/blob/master/Pipfile",
+ "git_url": "https://api.github.com/repos/mozilla/mozillians-tests/git/blobs/11fc8c6d445a2302417c65b86fb771243a3a90b7",
+ "download_url": "https://raw.githubusercontent.com/mozilla/mozillians-tests/master/Pipfile",
+ "type": "file",
+ "content": "W1tzb3VyY2VdXQoKdXJsID0gImh0dHBzOi8vcHlwaS5vcmcvc2ltcGxlIgp2\nZXJpZnlfc3NsID0gdHJ1ZQpuYW1lID0gInB5cGkiCgoKW2Rldi1wYWNrYWdl\nc10KCgoKW3BhY2thZ2VzXQoKQmVhdXRpZnVsU291cCA9ICI9PTMuMi4xIgpm\nbGFrZTggPSAiPT0zLjYuMCIKZmxha2U4LWlzb3J0ID0gIj09Mi41Igptb3ps\nb2cgPSAiPT0zLjkiClB5UE9NID0gIj09Mi4yLjAiCnB5dGVzdCA9ICI9PTMu\nMTAuMSIKcHl0ZXN0LW1ldGFkYXRhID0gIj09MS43LjAiCnB5dGVzdC1zZWxl\nbml1bSA9ICI9PTEuMTQuMCIKcHl0ZXN0LXZhcmlhYmxlcyA9ICI9PTEuNy4x\nIgpweXRlc3QteGRpc3QgPSAiPT0xLjI0LjEiCnJlcXVlc3RzID0gIj09Mi4y\nMC4xIgpweW90cCA9ICI9PTIuMi43IgoKCltwYWNrYWdlcy5jb25maWdwYXJz\nZXJdCgp2ZXJzaW9uID0gIj09My41LjAiCm1hcmtlcnMgPSAicHl0aG9uX3Zl\ncnNpb24gPCAnMy41JyIKCgpbcGFja2FnZXMuZW51bTM0XQoKdmVyc2lvbiA9\nICI9PTEuMS42IgptYXJrZXJzID0gInB5dGhvbl92ZXJzaW9uIDwgJzMuNCci\nCg==\n",
+ "encoding": "base64",
+ "_links": {
+ "self": "https://api.github.com/repos/mozilla/mozillians-tests/contents/Pipfile?ref=master",
+ "git": "https://api.github.com/repos/mozilla/mozillians-tests/git/blobs/11fc8c6d445a2302417c65b86fb771243a3a90b7",
+ "html": "https://github.com/mozilla/mozillians-tests/blob/master/Pipfile"
+ }
+}
diff --git a/uv/spec/fixtures/github/contents_python_pipfile_unparseable.json b/uv/spec/fixtures/github/contents_python_pipfile_unparseable.json
new file mode 100644
index 00000000000..a9e7879e4e9
--- /dev/null
+++ b/uv/spec/fixtures/github/contents_python_pipfile_unparseable.json
@@ -0,0 +1,18 @@
+{
+ "name": "Pipfile",
+ "path": "Pipfile",
+ "sha": "11fc8c6d445a2302417c65b86fb771243a3a90b7",
+ "size": 541,
+ "url": "https://api.github.com/repos/mozilla/mozillians-tests/contents/Pipfile?ref=master",
+ "html_url": "https://github.com/mozilla/mozillians-tests/blob/master/Pipfile",
+ "git_url": "https://api.github.com/repos/mozilla/mozillians-tests/git/blobs/11fc8c6d445a2302417c65b86fb771243a3a90b7",
+ "download_url": "https://raw.githubusercontent.com/mozilla/mozillians-tests/master/Pipfile",
+ "type": "file",
+ "content": "W1tzb3VyY2VdXQp1cmwgPSAiaHR0cHM6Ly9weXBpLnB5dGhvbi5vcmcvc2lt\ncGxlIgp2ZXJpZnlfc3NsID0gdHJ1ZQoKW3BhY2thZ2VzXQpweXRlc3QgPSAi\nKiIKCltwYWNrYWdlc10KcmVxdWVzdHMgPSAiKiIK\n",
+ "encoding": "base64",
+ "_links": {
+ "self": "https://api.github.com/repos/mozilla/mozillians-tests/contents/Pipfile?ref=master",
+ "git": "https://api.github.com/repos/mozilla/mozillians-tests/git/blobs/11fc8c6d445a2302417c65b86fb771243a3a90b7",
+ "html": "https://github.com/mozilla/mozillians-tests/blob/master/Pipfile"
+ }
+}
diff --git a/uv/spec/fixtures/github/contents_python_pipfile_with_path_dep.json b/uv/spec/fixtures/github/contents_python_pipfile_with_path_dep.json
new file mode 100644
index 00000000000..59ff0a56ea6
--- /dev/null
+++ b/uv/spec/fixtures/github/contents_python_pipfile_with_path_dep.json
@@ -0,0 +1,18 @@
+{
+ "name": "Pipfile",
+ "path": "Pipfile",
+ "sha": "3e0fd729eb97bacb2c8abeaa1ef30e01101159a5",
+ "size": 423,
+ "url": "https://api.github.com/repos/requests/requests/contents/Pipfile?ref=master",
+ "html_url": "https://github.com/requests/requests/blob/master/Pipfile",
+ "git_url": "https://api.github.com/repos/requests/requests/git/blobs/3e0fd729eb97bacb2c8abeaa1ef30e01101159a5",
+ "download_url": "https://raw.githubusercontent.com/requests/requests/master/Pipfile",
+ "type": "file",
+ "content": "W1tzb3VyY2VdXQp1cmwgPSAiaHR0cHM6Ly9weXBpLm9yZy9zaW1wbGUiCnZl\ncmlmeV9zc2wgPSB0cnVlCm5hbWUgPSAicHlwaSIKCltwYWNrYWdlc10KbWtk\nb2NzID0gIioiCmp1cHl0ZXItY2xpZW50ID0gIioiCm5iY29udmVydCA9ICIq\nIgpuYmNvbnZlcnQtdXRpbHMgPSAiKiIKcHlnbWVudHMgPSAiKiIKcHltZG93\nbi1leHRlbnNpb25zID0gIioiCnRhYnVsYXRlID0gIioiCnBhbmRhcyA9ICIq\nIgpta2RvY3MtbWF0ZXJpYWwgPSAiKiIKaXB5a2VybmVsID0gIioiCmN5dGhv\nbiA9ICIqIiAjIFJlcXVpcmVkIHVudGlsIHB5cHJvaiBwcm92aWRlIGEgd2hl\nZWwgZm9yIDMuNwpweXByb2ogPSB7ZWRpdGFibGUgPSB0cnVlLCBnaXQgPSAi\naHR0cHM6Ly9naXRodWIuY29tL2pzd2hpdC9weXByb2ouZ2l0In0gIyBSZXF1\naXJlZCB1bnRpbCBweXByb2ogcHJvdmlkZSBhIHdoZWVsIGZvciAzLjcKZ2Vv\ncGFuZGFzID0gIioiCm51bXB5ZG9jID0gIioiCmJsYWNrID0gIj09MTguOWIw\nIgpjbGljayA9ICIqIgoiZDM2MDllYSIgPSB7ZWRpdGFibGUgPSB0cnVlLCBw\nYXRoID0gIi4vLi4vZmxvd21hY2hpbmUifQpkZXNjYXJ0ZXMgPSAiKiIKc2Vh\nYm9ybiA9ICIqIgoiM2ZmNDA0YSIgPSB7ZWRpdGFibGUgPSB0cnVlLCBwYXRo\nID0gIi4vLi4vZmxvd2NsaWVudCJ9Cm1rdGhlYXBpZG9jcyA9ICIqIgpta25v\ndGVib29rcyA9ICIqIgpmbGFzay1qd3QtZXh0ZW5kZWQgPSAiKiIKcXVhcnQg\nPSAiKiIKcHl0aG9uLWRvdGVudiA9ICIqIgoKW2Rldi1wYWNrYWdlc10KClty\nZXF1aXJlc10KcHl0aG9uX3ZlcnNpb24gPSAiMy43IgoKW3NjcmlwdHNdCmJ1\naWxkID0gImJhc2ggYnVpbGQuc2giCnNlcnZlID0gImJhc2ggYnVpbGQuc2gg\nc2VydmUgLS1kaXJ0eXJlbG9hZCIKZGVwbG95ID0gImJhc2ggYnVpbGQuc2gg\nZ2gtZGVwbG95Igo=\n",
+ "encoding": "base64",
+ "_links": {
+ "self": "https://api.github.com/repos/requests/requests/contents/Pipfile?ref=master",
+ "git": "https://api.github.com/repos/requests/requests/git/blobs/3e0fd729eb97bacb2c8abeaa1ef30e01101159a5",
+ "html": "https://github.com/requests/requests/blob/master/Pipfile"
+ }
+}
diff --git a/uv/spec/fixtures/github/contents_python_pyproject.json b/uv/spec/fixtures/github/contents_python_pyproject.json
new file mode 100644
index 00000000000..e1e295b51fa
--- /dev/null
+++ b/uv/spec/fixtures/github/contents_python_pyproject.json
@@ -0,0 +1,18 @@
+{
+ "name": "pyproject.toml",
+ "path": "pyproject.toml",
+ "sha": "1ebadf060e206ca2414c1facbdeb7f8253f2d597",
+ "size": 1798,
+ "url": "https://api.github.com/repos/sdispater/poetry/contents/pyproject.toml?ref=master",
+ "html_url": "https://github.com/sdispater/poetry/blob/master/pyproject.toml",
+ "git_url": "https://api.github.com/repos/sdispater/poetry/git/blobs/1ebadf060e206ca2414c1facbdeb7f8253f2d597",
+ "download_url": "https://raw.githubusercontent.com/sdispater/poetry/master/pyproject.toml",
+ "type": "file",
+ "content": "W3Rvb2wucG9ldHJ5XQpuYW1lID0gInBvZXRyeSIKdmVyc2lvbiA9ICIwLjEy\nLjExIgpkZXNjcmlwdGlvbiA9ICJQeXRob24gZGVwZW5kZW5jeSBtYW5hZ2Vt\nZW50IGFuZCBwYWNrYWdpbmcgbWFkZSBlYXN5LiIKYXV0aG9ycyA9IFsKICAg\nICJTw6liYXN0aWVuIEV1c3RhY2UgPHNlYmFzdGllbkBldXN0YWNlLmlvPiIK\nXQpsaWNlbnNlID0gIk1JVCIKCnJlYWRtZSA9ICJSRUFETUUubWQiCgpob21l\ncGFnZSA9ICJodHRwczovL3BvZXRyeS5ldXN0YWNlLmlvLyIKcmVwb3NpdG9y\neSA9ICJodHRwczovL2dpdGh1Yi5jb20vc2Rpc3BhdGVyL3BvZXRyeSIKZG9j\ndW1lbnRhdGlvbiA9ICJodHRwczovL3BvZXRyeS5ldXN0YWNlLmlvL2RvY3Mi\nCgprZXl3b3JkcyA9IFsicGFja2FnaW5nIiwgImRlcGVuZGVuY3kiLCAicG9l\ndHJ5Il0KCmNsYXNzaWZpZXJzID0gWwogICAgIlRvcGljIDo6IFNvZnR3YXJl\nIERldmVsb3BtZW50IDo6IEJ1aWxkIFRvb2xzIiwKICAgICJUb3BpYyA6OiBT\nb2Z0d2FyZSBEZXZlbG9wbWVudCA6OiBMaWJyYXJpZXMgOjogUHl0aG9uIE1v\nZHVsZXMiCl0KCiMgUmVxdWlyZW1lbnRzClt0b29sLnBvZXRyeS5kZXBlbmRl\nbmNpZXNdCnB5dGhvbiA9ICJ+Mi43IHx8IF4zLjQiCmNsZW8gPSAiXjAuNi43\nIgpyZXF1ZXN0cyA9ICJeMi4xOCIKY2FjaHkgPSAiXjAuMiIKcmVxdWVzdHMt\ndG9vbGJlbHQgPSAiXjAuOC4wIgpqc29uc2NoZW1hID0gIl4zLjBhMyIKcHly\nc2lzdGVudCA9ICJeMC4xNC4yIgpweXBhcnNpbmcgPSAiXjIuMiIKY2FjaGVj\nb250cm9sID0geyB2ZXJzaW9uID0gIl4wLjEyLjQiLCBleHRyYXMgPSBbImZp\nbGVjYWNoZSJdIH0KcGtnaW5mbyA9ICJeMS40IgpodG1sNWxpYiA9ICJeMS4w\nIgpzaGVsbGluZ2hhbSA9ICJeMS4xIgp0b21sa2l0ID0gIl4wLjUuMSIKCiMg\nVGhlIHR5cGluZyBtb2R1bGUgaXMgbm90IGluIHRoZSBzdGRsaWIgaW4gUHl0\naG9uIDIuNyBhbmQgMy40CnR5cGluZyA9IHsgdmVyc2lvbiA9ICJeMy42Iiwg\ncHl0aG9uID0gIn4yLjcgfHwgfjMuNCIgfQoKIyBVc2UgcGF0aGxpYjIgZm9y\nIFB5dGhvbiAyLjcgYW5kIDMuNApwYXRobGliMiA9IHsgdmVyc2lvbiA9ICJe\nMi4zIiwgcHl0aG9uID0gIn4yLjcgfHwgfjMuNCIgfQojIFVzZSBnbG9iMiBm\nb3IgUHl0aG9uIDIuNyBhbmQgMy40Cmdsb2IyID0geyB2ZXJzaW9uID0gIl4w\nLjYiLCBweXRob24gPSAifjIuNyB8fCB+My40IiB9CiMgVXNlIHZpcnR1YWxl\nbnYgZm9yIFB5dGhvbiAyLjcgc2luY2UgdmVudiBkb2VzIG5vdCBleGlzdAp2\naXJ0dWFsZW52ID0geyB2ZXJzaW9uID0gIl4xNi4wIiwgcHl0aG9uID0gIn4y\nLjciIH0KIyBmdW5jdG9vbHMzMiBpcyBuZWVkZWQgZm9yIFB5dGhvbiAyLjcK\nZnVuY3Rvb2xzMzIgPSB7IHZlcnNpb24gPSAiXjMuMi4zIiwgcHl0aG9uID0g\nIn4yLjciIH0KClt0b29sLnBvZXRyeS5kZXYtZGVwZW5kZW5jaWVzXQpweXRl\nc3QgPSAiXjQuMSIKcHl0ZXN0LWNvdiA9ICJeMi41Igpta2RvY3MgPSB7IHZl\ncnNpb24gPSAiXjEuMCIsIHB5dGhvbiA9ICJ+Mi43LjkgfHwgXjMuNCIgfQpw\neW1kb3duLWV4dGVuc2lvbnMgPSAiXjYuMCIKcHlnbWVudHMgPSAiXjIuMiIK\ncHl0ZXN0LW1vY2sgPSAiXjEuOSIKcHlnbWVudHMtZ2l0aHViLWxleGVycyA9\nICJeMC4wLjUiCmJsYWNrID0geyB2ZXJzaW9uID0gIl4xOC4zLWFscGhhLjAi\nLCBweXRob24gPSAiXjMuNiIgfQpwcmUtY29tbWl0ID0gIl4xLjEwIgp0b3gg\nPSAiXjMuMCIKcHl0ZXN0LXN1Z2FyID0gIl4wLjkuMiIKCgpbdG9vbC5wb2V0\ncnkuc2NyaXB0c10KcG9ldHJ5ID0gInBvZXRyeS5jb25zb2xlOm1haW4iCg==\n",
+ "encoding": "base64",
+ "_links": {
+ "self": "https://api.github.com/repos/sdispater/poetry/contents/pyproject.toml?ref=master",
+ "git": "https://api.github.com/repos/sdispater/poetry/git/blobs/1ebadf060e206ca2414c1facbdeb7f8253f2d597",
+ "html": "https://github.com/sdispater/poetry/blob/master/pyproject.toml"
+ }
+}
diff --git a/uv/spec/fixtures/github/contents_python_pyproject_and_pdm_lock.json b/uv/spec/fixtures/github/contents_python_pyproject_and_pdm_lock.json
new file mode 100644
index 00000000000..3b3eb305627
--- /dev/null
+++ b/uv/spec/fixtures/github/contents_python_pyproject_and_pdm_lock.json
@@ -0,0 +1,146 @@
+[
+ {
+ "name": ".gitignore",
+ "path": ".gitignore",
+ "sha": "69cb8deeb32e391d4c7468bcb946d1dcc4a18f7e",
+ "size": 50,
+ "url": "https://api.github.com/repos/pdm-project/setup-pdm/contents/.gitignore?ref=main",
+ "html_url": "https://github.com/pdm-project/setup-pdm/blob/main/.gitignore",
+ "git_url": "https://api.github.com/repos/pdm-project/setup-pdm/git/blobs/69cb8deeb32e391d4c7468bcb946d1dcc4a18f7e",
+ "download_url": "https://raw.githubusercontent.com/pdm-project/setup-pdm/main/.gitignore",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/pdm-project/setup-pdm/contents/.gitignore?ref=main",
+ "git": "https://api.github.com/repos/pdm-project/setup-pdm/git/blobs/69cb8deeb32e391d4c7468bcb946d1dcc4a18f7e",
+ "html": "https://github.com/pdm-project/setup-pdm/blob/main/.gitignore"
+ }
+ },
+ {
+ "name": "LICENSE",
+ "path": "LICENSE",
+ "sha": "84fe533754a50b4ebba98d31711e44fda16e78ec",
+ "size": 1068,
+ "url": "https://api.github.com/repos/pdm-project/setup-pdm/contents/LICENSE?ref=main",
+ "html_url": "https://github.com/pdm-project/setup-pdm/blob/main/LICENSE",
+ "git_url": "https://api.github.com/repos/pdm-project/setup-pdm/git/blobs/84fe533754a50b4ebba98d31711e44fda16e78ec",
+ "download_url": "https://raw.githubusercontent.com/pdm-project/setup-pdm/main/LICENSE",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/pdm-project/setup-pdm/contents/LICENSE?ref=main",
+ "git": "https://api.github.com/repos/pdm-project/setup-pdm/git/blobs/84fe533754a50b4ebba98d31711e44fda16e78ec",
+ "html": "https://github.com/pdm-project/setup-pdm/blob/main/LICENSE"
+ }
+ },
+ {
+ "name": "README.md",
+ "path": "README.md",
+ "sha": "0aef9494ec8522bd282da9d9fdfabce2e37772e9",
+ "size": 1489,
+ "url": "https://api.github.com/repos/pdm-project/setup-pdm/contents/README.md?ref=main",
+ "html_url": "https://github.com/pdm-project/setup-pdm/blob/main/README.md",
+ "git_url": "https://api.github.com/repos/pdm-project/setup-pdm/git/blobs/0aef9494ec8522bd282da9d9fdfabce2e37772e9",
+ "download_url": "https://raw.githubusercontent.com/pdm-project/setup-pdm/main/README.md",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/pdm-project/setup-pdm/contents/README.md?ref=main",
+ "git": "https://api.github.com/repos/pdm-project/setup-pdm/git/blobs/0aef9494ec8522bd282da9d9fdfabce2e37772e9",
+ "html": "https://github.com/pdm-project/setup-pdm/blob/main/README.md"
+ }
+ },
+ {
+ "name": "action.yml",
+ "path": "action.yml",
+ "sha": "ce06edd0371247671900428088c35db33b47ea40",
+ "size": 1119,
+ "url": "https://api.github.com/repos/pdm-project/setup-pdm/contents/action.yml?ref=main",
+ "html_url": "https://github.com/pdm-project/setup-pdm/blob/main/action.yml",
+ "git_url": "https://api.github.com/repos/pdm-project/setup-pdm/git/blobs/ce06edd0371247671900428088c35db33b47ea40",
+ "download_url": "https://raw.githubusercontent.com/pdm-project/setup-pdm/main/action.yml",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/pdm-project/setup-pdm/contents/action.yml?ref=main",
+ "git": "https://api.github.com/repos/pdm-project/setup-pdm/git/blobs/ce06edd0371247671900428088c35db33b47ea40",
+ "html": "https://github.com/pdm-project/setup-pdm/blob/main/action.yml"
+ }
+ },
+ {
+ "name": "package.json",
+ "path": "package.json",
+ "sha": "bdbc5fb8c2f171476b749c74b3c18886402fc58f",
+ "size": 668,
+ "url": "https://api.github.com/repos/pdm-project/setup-pdm/contents/package.json?ref=main",
+ "html_url": "https://github.com/pdm-project/setup-pdm/blob/main/package.json",
+ "git_url": "https://api.github.com/repos/pdm-project/setup-pdm/git/blobs/bdbc5fb8c2f171476b749c74b3c18886402fc58f",
+ "download_url": "https://raw.githubusercontent.com/pdm-project/setup-pdm/main/package.json",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/pdm-project/setup-pdm/contents/package.json?ref=main",
+ "git": "https://api.github.com/repos/pdm-project/setup-pdm/git/blobs/bdbc5fb8c2f171476b749c74b3c18886402fc58f",
+ "html": "https://github.com/pdm-project/setup-pdm/blob/main/package.json"
+ }
+ },
+ {
+ "name": "pdm.lock",
+ "path": "pdm.lock",
+ "sha": "31a43a994d33ec6fab0a26a08b7313c6836e0822",
+ "size": 3281,
+ "url": "https://api.github.com/repos/pdm-project/setup-pdm/contents/pdm.lock?ref=main",
+ "html_url": "https://github.com/pdm-project/setup-pdm/blob/main/pdm.lock",
+ "git_url": "https://api.github.com/repos/pdm-project/setup-pdm/git/blobs/31a43a994d33ec6fab0a26a08b7313c6836e0822",
+ "download_url": "https://raw.githubusercontent.com/pdm-project/setup-pdm/main/pdm.lock",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/pdm-project/setup-pdm/contents/pdm.lock?ref=main",
+ "git": "https://api.github.com/repos/pdm-project/setup-pdm/git/blobs/31a43a994d33ec6fab0a26a08b7313c6836e0822",
+ "html": "https://github.com/pdm-project/setup-pdm/blob/main/pdm.lock"
+ }
+ },
+ {
+ "name": "pyproject.toml",
+ "path": "pyproject.toml",
+ "sha": "ef878626903d08844f17dec880ec944c2312ccd5",
+ "size": 526,
+ "url": "https://api.github.com/repos/pdm-project/setup-pdm/contents/pyproject.toml?ref=main",
+ "html_url": "https://github.com/pdm-project/setup-pdm/blob/main/pyproject.toml",
+ "git_url": "https://api.github.com/repos/pdm-project/setup-pdm/git/blobs/ef878626903d08844f17dec880ec944c2312ccd5",
+ "download_url": "https://raw.githubusercontent.com/pdm-project/setup-pdm/main/pyproject.toml",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/pdm-project/setup-pdm/contents/pyproject.toml?ref=main",
+ "git": "https://api.github.com/repos/pdm-project/setup-pdm/git/blobs/ef878626903d08844f17dec880ec944c2312ccd5",
+ "html": "https://github.com/pdm-project/setup-pdm/blob/main/pyproject.toml"
+ }
+ },
+ {
+ "name": "test.py",
+ "path": "test.py",
+ "sha": "f4f28c78d3f907d97dc3d74d411e9d28aa8df4af",
+ "size": 1052,
+ "url": "https://api.github.com/repos/pdm-project/setup-pdm/contents/test.py?ref=main",
+ "html_url": "https://github.com/pdm-project/setup-pdm/blob/main/test.py",
+ "git_url": "https://api.github.com/repos/pdm-project/setup-pdm/git/blobs/f4f28c78d3f907d97dc3d74d411e9d28aa8df4af",
+ "download_url": "https://raw.githubusercontent.com/pdm-project/setup-pdm/main/test.py",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/pdm-project/setup-pdm/contents/test.py?ref=main",
+ "git": "https://api.github.com/repos/pdm-project/setup-pdm/git/blobs/f4f28c78d3f907d97dc3d74d411e9d28aa8df4af",
+ "html": "https://github.com/pdm-project/setup-pdm/blob/main/test.py"
+ }
+ },
+ {
+ "name": "tsconfig.json",
+ "path": "tsconfig.json",
+ "sha": "9e1ee252d05cfcafa70d459f87edc45cb2262926",
+ "size": 5523,
+ "url": "https://api.github.com/repos/pdm-project/setup-pdm/contents/tsconfig.json?ref=main",
+ "html_url": "https://github.com/pdm-project/setup-pdm/blob/main/tsconfig.json",
+ "git_url": "https://api.github.com/repos/pdm-project/setup-pdm/git/blobs/9e1ee252d05cfcafa70d459f87edc45cb2262926",
+ "download_url": "https://raw.githubusercontent.com/pdm-project/setup-pdm/main/tsconfig.json",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/pdm-project/setup-pdm/contents/tsconfig.json?ref=main",
+ "git": "https://api.github.com/repos/pdm-project/setup-pdm/git/blobs/9e1ee252d05cfcafa70d459f87edc45cb2262926",
+ "html": "https://github.com/pdm-project/setup-pdm/blob/main/tsconfig.json"
+ }
+ }
+]
diff --git a/uv/spec/fixtures/github/contents_python_pyproject_and_requirements_without_setup_py.json b/uv/spec/fixtures/github/contents_python_pyproject_and_requirements_without_setup_py.json
new file mode 100644
index 00000000000..b8e25c408b8
--- /dev/null
+++ b/uv/spec/fixtures/github/contents_python_pyproject_and_requirements_without_setup_py.json
@@ -0,0 +1,451 @@
+[
+ {
+ "name": ".codeclimate.yml",
+ "path": ".codeclimate.yml",
+ "sha": "6393602fac96cfe31d64f89476014124b4a13b85",
+ "size": 416,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.codeclimate.yml?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.codeclimate.yml",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/6393602fac96cfe31d64f89476014124b4a13b85",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/.codeclimate.yml",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.codeclimate.yml?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/6393602fac96cfe31d64f89476014124b4a13b85",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.codeclimate.yml"
+ }
+ },
+ {
+ "name": ".coveragerc",
+ "path": ".coveragerc",
+ "sha": "be7fdc86067d0924f3e1e92c1a3ed92d9486fcbb",
+ "size": 646,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.coveragerc?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.coveragerc",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/be7fdc86067d0924f3e1e92c1a3ed92d9486fcbb",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/.coveragerc",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.coveragerc?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/be7fdc86067d0924f3e1e92c1a3ed92d9486fcbb",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.coveragerc"
+ }
+ },
+ {
+ "name": ".csslintrc",
+ "path": ".csslintrc",
+ "sha": "aacba956e5bbede1c195ce554fcad3e200b24ff8",
+ "size": 107,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.csslintrc?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.csslintrc",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/aacba956e5bbede1c195ce554fcad3e200b24ff8",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/.csslintrc",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.csslintrc?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/aacba956e5bbede1c195ce554fcad3e200b24ff8",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.csslintrc"
+ }
+ },
+ {
+ "name": ".env.example",
+ "path": ".env.example",
+ "sha": "d9f599b33ecd834ea88979dcc3daf4fcafacf4e7",
+ "size": 2617,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.env.example?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.env.example",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/d9f599b33ecd834ea88979dcc3daf4fcafacf4e7",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/.env.example",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.env.example?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/d9f599b33ecd834ea88979dcc3daf4fcafacf4e7",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.env.example"
+ }
+ },
+ {
+ "name": ".eslintignore",
+ "path": ".eslintignore",
+ "sha": "96212a3593bac8c93f624b77185a8d11018efd96",
+ "size": 16,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.eslintignore?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.eslintignore",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/96212a3593bac8c93f624b77185a8d11018efd96",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/.eslintignore",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.eslintignore?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/96212a3593bac8c93f624b77185a8d11018efd96",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.eslintignore"
+ }
+ },
+ {
+ "name": ".eslintrc.yml",
+ "path": ".eslintrc.yml",
+ "sha": "a6a0ce9c44238e06ff55ca335a66a4e16810da38",
+ "size": 6056,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.eslintrc.yml?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.eslintrc.yml",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/a6a0ce9c44238e06ff55ca335a66a4e16810da38",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/.eslintrc.yml",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.eslintrc.yml?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/a6a0ce9c44238e06ff55ca335a66a4e16810da38",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.eslintrc.yml"
+ }
+ },
+ {
+ "name": ".gitignore",
+ "path": ".gitignore",
+ "sha": "93923ac3a463bd17d0aefca2de9d2810f243d747",
+ "size": 1073,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.gitignore?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.gitignore",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/93923ac3a463bd17d0aefca2de9d2810f243d747",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/.gitignore",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.gitignore?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/93923ac3a463bd17d0aefca2de9d2810f243d747",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.gitignore"
+ }
+ },
+ {
+ "name": "LICENSE.md",
+ "path": "LICENSE.md",
+ "sha": "8dada3edaf50dbc082c9a125058f25def75e625a",
+ "size": 11357,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/LICENSE.md?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/LICENSE.md",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/8dada3edaf50dbc082c9a125058f25def75e625a",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/LICENSE.md",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/LICENSE.md?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/8dada3edaf50dbc082c9a125058f25def75e625a",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/LICENSE.md"
+ }
+ },
+ {
+ "name": "Procfile",
+ "path": "Procfile",
+ "sha": "72e4ef1be7c64eb0f874344bc8a6cf859bd39e00",
+ "size": 26,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/Procfile?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/Procfile",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/72e4ef1be7c64eb0f874344bc8a6cf859bd39e00",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/Procfile",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/Procfile?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/72e4ef1be7c64eb0f874344bc8a6cf859bd39e00",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/Procfile"
+ }
+ },
+ {
+ "name": "README.md",
+ "path": "README.md",
+ "sha": "01aae7d562fe164d2cee644e8ef5fba82d2b8e81",
+ "size": 1589,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/README.md?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/README.md",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/01aae7d562fe164d2cee644e8ef5fba82d2b8e81",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/README.md",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/README.md?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/01aae7d562fe164d2cee644e8ef5fba82d2b8e81",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/README.md"
+ }
+ },
+ {
+ "name": "Vagrantfile.example",
+ "path": "Vagrantfile.example",
+ "sha": "54be29ea9e1e2ecdbfa642656cded8b3cb85c910",
+ "size": 4329,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/Vagrantfile.example?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/Vagrantfile.example",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/54be29ea9e1e2ecdbfa642656cded8b3cb85c910",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/Vagrantfile.example",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/Vagrantfile.example?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/54be29ea9e1e2ecdbfa642656cded8b3cb85c910",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/Vagrantfile.example"
+ }
+ },
+ {
+ "name": "app",
+ "path": "app",
+ "sha": "f9e84e24364972f3aa4f92b869a622db1f260fa1",
+ "size": 0,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/app?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/app",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/f9e84e24364972f3aa4f92b869a622db1f260fa1",
+ "download_url": null,
+ "type": "dir",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/app?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/f9e84e24364972f3aa4f92b869a622db1f260fa1",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/app"
+ }
+ },
+ {
+ "name": "build_scripts",
+ "path": "build_scripts",
+ "sha": "be8e80f054e47f0c9a6fc9cfe5061346c6f8b2d0",
+ "size": 0,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/build_scripts?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/build_scripts",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/be8e80f054e47f0c9a6fc9cfe5061346c6f8b2d0",
+ "download_url": null,
+ "type": "dir",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/build_scripts?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/be8e80f054e47f0c9a6fc9cfe5061346c6f8b2d0",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/build_scripts"
+ }
+ },
+ {
+ "name": "celery_worker.py",
+ "path": "celery_worker.py",
+ "sha": "c84c73c1f1c1aa42550a08ae4f32dc955ced5f18",
+ "size": 279,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/celery_worker.py?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/celery_worker.py",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/c84c73c1f1c1aa42550a08ae4f32dc955ced5f18",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/celery_worker.py",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/celery_worker.py?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/c84c73c1f1c1aa42550a08ae4f32dc955ced5f18",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/celery_worker.py"
+ }
+ },
+ {
+ "name": "config.py",
+ "path": "config.py",
+ "sha": "2886556fc4844e708472a99a85b42b4f5b51d509",
+ "size": 8250,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/config.py?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/config.py",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/2886556fc4844e708472a99a85b42b4f5b51d509",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/config.py",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/config.py?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/2886556fc4844e708472a99a85b42b4f5b51d509",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/config.py"
+ }
+ },
+ {
+ "name": "crontab",
+ "path": "crontab",
+ "sha": "1e2c1da613e8272df6ece759565524c93bc76780",
+ "size": 300,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/crontab?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/crontab",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/1e2c1da613e8272df6ece759565524c93bc76780",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/crontab",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/crontab?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/1e2c1da613e8272df6ece759565524c93bc76780",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/crontab"
+ }
+ },
+ {
+ "name": "data",
+ "path": "data",
+ "sha": "7bceca86ff0e88cb53c8828d441f5e0725776395",
+ "size": 0,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/data?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/data",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/7bceca86ff0e88cb53c8828d441f5e0725776395",
+ "download_url": null,
+ "type": "dir",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/data?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/7bceca86ff0e88cb53c8828d441f5e0725776395",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/data"
+ }
+ },
+ {
+ "name": "gunicorn_config.py",
+ "path": "gunicorn_config.py",
+ "sha": "7b1a455133c2e78611550e45e8d2072d5c5c4ad7",
+ "size": 2504,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/gunicorn_config.py?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/gunicorn_config.py",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/7b1a455133c2e78611550e45e8d2072d5c5c4ad7",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/gunicorn_config.py",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/gunicorn_config.py?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/7b1a455133c2e78611550e45e8d2072d5c5c4ad7",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/gunicorn_config.py"
+ }
+ },
+ {
+ "name": "jobs.py",
+ "path": "jobs.py",
+ "sha": "79f2957e2c94e44786f6ca3dfc7384aaceb80c0a",
+ "size": 6213,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/jobs.py?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/jobs.py",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/79f2957e2c94e44786f6ca3dfc7384aaceb80c0a",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/jobs.py",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/jobs.py?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/79f2957e2c94e44786f6ca3dfc7384aaceb80c0a",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/jobs.py"
+ }
+ },
+ {
+ "name": "magic",
+ "path": "magic",
+ "sha": "6342094c1d4b1af948867ffba67cf0b866e5613c",
+ "size": 659195,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/magic?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/magic",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/6342094c1d4b1af948867ffba67cf0b866e5613c",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/magic",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/magic?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/6342094c1d4b1af948867ffba67cf0b866e5613c",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/magic"
+ }
+ },
+ {
+ "name": "manage.py",
+ "path": "manage.py",
+ "sha": "a0b80d4c7b5fd7e50d6dcb5bcbdcd995b8da27f0",
+ "size": 15323,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/manage.py?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/manage.py",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/a0b80d4c7b5fd7e50d6dcb5bcbdcd995b8da27f0",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/manage.py",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/manage.py?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/a0b80d4c7b5fd7e50d6dcb5bcbdcd995b8da27f0",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/manage.py"
+ }
+ },
+ {
+ "name": "migrations",
+ "path": "migrations",
+ "sha": "da206a9809330d01f4800718bca2a20c05038b44",
+ "size": 0,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/migrations?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/migrations",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/da206a9809330d01f4800718bca2a20c05038b44",
+ "download_url": null,
+ "type": "dir",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/migrations?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/da206a9809330d01f4800718bca2a20c05038b44",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/migrations"
+ }
+ },
+{
+ "name": "requirements-test.txt",
+ "path": "requirements-test.txt",
+ "sha": "88b4e0a1c8093fae2b4fa52534035f9f85ed0956",
+ "size": 2433,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/requirements-test.txt?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/requirements-test.txt",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/88b4e0a1c8093fae2b4fa52534035f9f85ed0956",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/requirements-test.txt",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/requirements-test.txt?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/88b4e0a1c8093fae2b4fa52534035f9f85ed0956",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/requirements-test.txt"
+ }
+ },
+
+ {
+ "name": "setup.cfg",
+ "path": "setup.cfg",
+ "sha": "88b4e0a1c8093fae2b4fa52534035f9f85ed0956",
+ "size": 2433,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/setup.cfg?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/setup.cfg",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/88b4e0a1c8093fae2b4fa52534035f9f85ed0956",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/setup.cfg",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/setup.cfg?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/88b4e0a1c8093fae2b4fa52534035f9f85ed0956",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/setup.cfg"
+ }
+ },
+ {
+ "name": "tests",
+ "path": "tests",
+ "sha": "88b4e0a1c8093fae2b4fa52534035f9f85ed0956",
+ "size": 0,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/tests?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/tests",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/88b4e0a1c8093fae2b4fa52534035f9f85ed0956",
+ "download_url": null,
+ "type": "dir",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/tests?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/88b4e0a1c8093fae2b4fa52534035f9f85ed0956",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/tests"
+ }
+ },
+ {
+ "name": "todo.txt",
+ "path": "todo.txt",
+ "sha": "3e369beef1c9e64f0c10735d35aa8ad755daddc6",
+ "size": 1147,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/todo.txt?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/todo.txt",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/3e369beef1c9e64f0c10735d35aa8ad755daddc6",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/todo.txt",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/todo.txt?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/3e369beef1c9e64f0c10735d35aa8ad755daddc6",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/todo.txt"
+ }
+ },
+ {
+ "name": "update_definitions.sh",
+ "path": "update_definitions.sh",
+ "sha": "fbde266ea5ebd519b94d18f8f78ab825b02766df",
+ "size": 7877,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/update_definitions.sh?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/update_definitions.sh",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/fbde266ea5ebd519b94d18f8f78ab825b02766df",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/update_definitions.sh",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/update_definitions.sh?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/fbde266ea5ebd519b94d18f8f78ab825b02766df",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/update_definitions.sh"
+ }
+ },
+ {
+ "name": "pyproject.toml",
+ "path": "pyproject.toml",
+ "sha": "e003114331b9777c5ff4bf3915ae98f08a972a41",
+ "size": 709,
+ "url": "https://api.github.com/repos/sdispater/pendulum/contents/pyproject.toml?ref=master",
+ "html_url": "https://github.com/sdispater/pendulum/blob/master/pyproject.toml",
+ "git_url": "https://api.github.com/repos/sdispater/pendulum/git/blobs/e003114331b9777c5ff4bf3915ae98f08a972a41",
+ "download_url": "https://raw.githubusercontent.com/sdispater/pendulum/master/pyproject.toml",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/sdispater/pendulum/contents/pyproject.toml?ref=master",
+ "git": "https://api.github.com/repos/sdispater/pendulum/git/blobs/e003114331b9777c5ff4bf3915ae98f08a972a41",
+ "html": "https://github.com/sdispater/pendulum/blob/master/pyproject.toml"
+ }
+ }
+]
diff --git a/uv/spec/fixtures/github/contents_python_pyproject_and_setup_cfg.json b/uv/spec/fixtures/github/contents_python_pyproject_and_setup_cfg.json
new file mode 100644
index 00000000000..dbdaf5fcd88
--- /dev/null
+++ b/uv/spec/fixtures/github/contents_python_pyproject_and_setup_cfg.json
@@ -0,0 +1,434 @@
+[
+ {
+ "name": ".codeclimate.yml",
+ "path": ".codeclimate.yml",
+ "sha": "6393602fac96cfe31d64f89476014124b4a13b85",
+ "size": 416,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.codeclimate.yml?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.codeclimate.yml",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/6393602fac96cfe31d64f89476014124b4a13b85",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/.codeclimate.yml",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.codeclimate.yml?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/6393602fac96cfe31d64f89476014124b4a13b85",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.codeclimate.yml"
+ }
+ },
+ {
+ "name": ".coveragerc",
+ "path": ".coveragerc",
+ "sha": "be7fdc86067d0924f3e1e92c1a3ed92d9486fcbb",
+ "size": 646,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.coveragerc?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.coveragerc",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/be7fdc86067d0924f3e1e92c1a3ed92d9486fcbb",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/.coveragerc",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.coveragerc?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/be7fdc86067d0924f3e1e92c1a3ed92d9486fcbb",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.coveragerc"
+ }
+ },
+ {
+ "name": ".csslintrc",
+ "path": ".csslintrc",
+ "sha": "aacba956e5bbede1c195ce554fcad3e200b24ff8",
+ "size": 107,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.csslintrc?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.csslintrc",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/aacba956e5bbede1c195ce554fcad3e200b24ff8",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/.csslintrc",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.csslintrc?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/aacba956e5bbede1c195ce554fcad3e200b24ff8",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.csslintrc"
+ }
+ },
+ {
+ "name": ".env.example",
+ "path": ".env.example",
+ "sha": "d9f599b33ecd834ea88979dcc3daf4fcafacf4e7",
+ "size": 2617,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.env.example?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.env.example",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/d9f599b33ecd834ea88979dcc3daf4fcafacf4e7",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/.env.example",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.env.example?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/d9f599b33ecd834ea88979dcc3daf4fcafacf4e7",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.env.example"
+ }
+ },
+ {
+ "name": ".eslintignore",
+ "path": ".eslintignore",
+ "sha": "96212a3593bac8c93f624b77185a8d11018efd96",
+ "size": 16,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.eslintignore?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.eslintignore",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/96212a3593bac8c93f624b77185a8d11018efd96",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/.eslintignore",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.eslintignore?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/96212a3593bac8c93f624b77185a8d11018efd96",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.eslintignore"
+ }
+ },
+ {
+ "name": ".eslintrc.yml",
+ "path": ".eslintrc.yml",
+ "sha": "a6a0ce9c44238e06ff55ca335a66a4e16810da38",
+ "size": 6056,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.eslintrc.yml?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.eslintrc.yml",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/a6a0ce9c44238e06ff55ca335a66a4e16810da38",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/.eslintrc.yml",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.eslintrc.yml?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/a6a0ce9c44238e06ff55ca335a66a4e16810da38",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.eslintrc.yml"
+ }
+ },
+ {
+ "name": ".gitignore",
+ "path": ".gitignore",
+ "sha": "93923ac3a463bd17d0aefca2de9d2810f243d747",
+ "size": 1073,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.gitignore?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.gitignore",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/93923ac3a463bd17d0aefca2de9d2810f243d747",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/.gitignore",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.gitignore?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/93923ac3a463bd17d0aefca2de9d2810f243d747",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.gitignore"
+ }
+ },
+ {
+ "name": "LICENSE.md",
+ "path": "LICENSE.md",
+ "sha": "8dada3edaf50dbc082c9a125058f25def75e625a",
+ "size": 11357,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/LICENSE.md?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/LICENSE.md",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/8dada3edaf50dbc082c9a125058f25def75e625a",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/LICENSE.md",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/LICENSE.md?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/8dada3edaf50dbc082c9a125058f25def75e625a",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/LICENSE.md"
+ }
+ },
+ {
+ "name": "Procfile",
+ "path": "Procfile",
+ "sha": "72e4ef1be7c64eb0f874344bc8a6cf859bd39e00",
+ "size": 26,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/Procfile?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/Procfile",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/72e4ef1be7c64eb0f874344bc8a6cf859bd39e00",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/Procfile",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/Procfile?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/72e4ef1be7c64eb0f874344bc8a6cf859bd39e00",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/Procfile"
+ }
+ },
+ {
+ "name": "README.md",
+ "path": "README.md",
+ "sha": "01aae7d562fe164d2cee644e8ef5fba82d2b8e81",
+ "size": 1589,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/README.md?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/README.md",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/01aae7d562fe164d2cee644e8ef5fba82d2b8e81",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/README.md",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/README.md?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/01aae7d562fe164d2cee644e8ef5fba82d2b8e81",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/README.md"
+ }
+ },
+ {
+ "name": "Vagrantfile.example",
+ "path": "Vagrantfile.example",
+ "sha": "54be29ea9e1e2ecdbfa642656cded8b3cb85c910",
+ "size": 4329,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/Vagrantfile.example?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/Vagrantfile.example",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/54be29ea9e1e2ecdbfa642656cded8b3cb85c910",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/Vagrantfile.example",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/Vagrantfile.example?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/54be29ea9e1e2ecdbfa642656cded8b3cb85c910",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/Vagrantfile.example"
+ }
+ },
+ {
+ "name": "app",
+ "path": "app",
+ "sha": "f9e84e24364972f3aa4f92b869a622db1f260fa1",
+ "size": 0,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/app?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/app",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/f9e84e24364972f3aa4f92b869a622db1f260fa1",
+ "download_url": null,
+ "type": "dir",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/app?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/f9e84e24364972f3aa4f92b869a622db1f260fa1",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/app"
+ }
+ },
+ {
+ "name": "build_scripts",
+ "path": "build_scripts",
+ "sha": "be8e80f054e47f0c9a6fc9cfe5061346c6f8b2d0",
+ "size": 0,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/build_scripts?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/build_scripts",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/be8e80f054e47f0c9a6fc9cfe5061346c6f8b2d0",
+ "download_url": null,
+ "type": "dir",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/build_scripts?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/be8e80f054e47f0c9a6fc9cfe5061346c6f8b2d0",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/build_scripts"
+ }
+ },
+ {
+ "name": "celery_worker.py",
+ "path": "celery_worker.py",
+ "sha": "c84c73c1f1c1aa42550a08ae4f32dc955ced5f18",
+ "size": 279,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/celery_worker.py?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/celery_worker.py",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/c84c73c1f1c1aa42550a08ae4f32dc955ced5f18",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/celery_worker.py",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/celery_worker.py?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/c84c73c1f1c1aa42550a08ae4f32dc955ced5f18",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/celery_worker.py"
+ }
+ },
+ {
+ "name": "config.py",
+ "path": "config.py",
+ "sha": "2886556fc4844e708472a99a85b42b4f5b51d509",
+ "size": 8250,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/config.py?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/config.py",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/2886556fc4844e708472a99a85b42b4f5b51d509",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/config.py",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/config.py?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/2886556fc4844e708472a99a85b42b4f5b51d509",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/config.py"
+ }
+ },
+ {
+ "name": "crontab",
+ "path": "crontab",
+ "sha": "1e2c1da613e8272df6ece759565524c93bc76780",
+ "size": 300,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/crontab?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/crontab",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/1e2c1da613e8272df6ece759565524c93bc76780",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/crontab",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/crontab?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/1e2c1da613e8272df6ece759565524c93bc76780",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/crontab"
+ }
+ },
+ {
+ "name": "data",
+ "path": "data",
+ "sha": "7bceca86ff0e88cb53c8828d441f5e0725776395",
+ "size": 0,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/data?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/data",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/7bceca86ff0e88cb53c8828d441f5e0725776395",
+ "download_url": null,
+ "type": "dir",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/data?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/7bceca86ff0e88cb53c8828d441f5e0725776395",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/data"
+ }
+ },
+ {
+ "name": "gunicorn_config.py",
+ "path": "gunicorn_config.py",
+ "sha": "7b1a455133c2e78611550e45e8d2072d5c5c4ad7",
+ "size": 2504,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/gunicorn_config.py?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/gunicorn_config.py",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/7b1a455133c2e78611550e45e8d2072d5c5c4ad7",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/gunicorn_config.py",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/gunicorn_config.py?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/7b1a455133c2e78611550e45e8d2072d5c5c4ad7",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/gunicorn_config.py"
+ }
+ },
+ {
+ "name": "jobs.py",
+ "path": "jobs.py",
+ "sha": "79f2957e2c94e44786f6ca3dfc7384aaceb80c0a",
+ "size": 6213,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/jobs.py?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/jobs.py",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/79f2957e2c94e44786f6ca3dfc7384aaceb80c0a",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/jobs.py",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/jobs.py?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/79f2957e2c94e44786f6ca3dfc7384aaceb80c0a",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/jobs.py"
+ }
+ },
+ {
+ "name": "magic",
+ "path": "magic",
+ "sha": "6342094c1d4b1af948867ffba67cf0b866e5613c",
+ "size": 659195,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/magic?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/magic",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/6342094c1d4b1af948867ffba67cf0b866e5613c",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/magic",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/magic?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/6342094c1d4b1af948867ffba67cf0b866e5613c",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/magic"
+ }
+ },
+ {
+ "name": "manage.py",
+ "path": "manage.py",
+ "sha": "a0b80d4c7b5fd7e50d6dcb5bcbdcd995b8da27f0",
+ "size": 15323,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/manage.py?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/manage.py",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/a0b80d4c7b5fd7e50d6dcb5bcbdcd995b8da27f0",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/manage.py",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/manage.py?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/a0b80d4c7b5fd7e50d6dcb5bcbdcd995b8da27f0",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/manage.py"
+ }
+ },
+ {
+ "name": "migrations",
+ "path": "migrations",
+ "sha": "da206a9809330d01f4800718bca2a20c05038b44",
+ "size": 0,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/migrations?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/migrations",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/da206a9809330d01f4800718bca2a20c05038b44",
+ "download_url": null,
+ "type": "dir",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/migrations?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/da206a9809330d01f4800718bca2a20c05038b44",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/migrations"
+ }
+ },
+ {
+ "name": "setup.cfg",
+ "path": "setup.cfg",
+ "sha": "88b4e0a1c8093fae2b4fa52534035f9f85ed0956",
+ "size": 2433,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/setup.cfg?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/setup.cfg",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/88b4e0a1c8093fae2b4fa52534035f9f85ed0956",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/setup.cfg",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/setup.cfg?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/88b4e0a1c8093fae2b4fa52534035f9f85ed0956",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/setup.cfg"
+ }
+ },
+ {
+ "name": "tests",
+ "path": "tests",
+ "sha": "88b4e0a1c8093fae2b4fa52534035f9f85ed0956",
+ "size": 0,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/tests?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/tests",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/88b4e0a1c8093fae2b4fa52534035f9f85ed0956",
+ "download_url": null,
+ "type": "dir",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/tests?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/88b4e0a1c8093fae2b4fa52534035f9f85ed0956",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/tests"
+ }
+ },
+ {
+ "name": "todo.txt",
+ "path": "todo.txt",
+ "sha": "3e369beef1c9e64f0c10735d35aa8ad755daddc6",
+ "size": 1147,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/todo.txt?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/todo.txt",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/3e369beef1c9e64f0c10735d35aa8ad755daddc6",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/todo.txt",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/todo.txt?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/3e369beef1c9e64f0c10735d35aa8ad755daddc6",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/todo.txt"
+ }
+ },
+ {
+ "name": "update_definitions.sh",
+ "path": "update_definitions.sh",
+ "sha": "fbde266ea5ebd519b94d18f8f78ab825b02766df",
+ "size": 7877,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/update_definitions.sh?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/update_definitions.sh",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/fbde266ea5ebd519b94d18f8f78ab825b02766df",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/update_definitions.sh",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/update_definitions.sh?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/fbde266ea5ebd519b94d18f8f78ab825b02766df",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/update_definitions.sh"
+ }
+ },
+ {
+ "name": "pyproject.toml",
+ "path": "pyproject.toml",
+ "sha": "e003114331b9777c5ff4bf3915ae98f08a972a41",
+ "size": 709,
+ "url": "https://api.github.com/repos/sdispater/pendulum/contents/pyproject.toml?ref=master",
+ "html_url": "https://github.com/sdispater/pendulum/blob/master/pyproject.toml",
+ "git_url": "https://api.github.com/repos/sdispater/pendulum/git/blobs/e003114331b9777c5ff4bf3915ae98f08a972a41",
+ "download_url": "https://raw.githubusercontent.com/sdispater/pendulum/master/pyproject.toml",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/sdispater/pendulum/contents/pyproject.toml?ref=master",
+ "git": "https://api.github.com/repos/sdispater/pendulum/git/blobs/e003114331b9777c5ff4bf3915ae98f08a972a41",
+ "html": "https://github.com/sdispater/pendulum/blob/master/pyproject.toml"
+ }
+ }
+]
diff --git a/uv/spec/fixtures/github/contents_python_repo.json b/uv/spec/fixtures/github/contents_python_repo.json
new file mode 100644
index 00000000000..f78d8350fd5
--- /dev/null
+++ b/uv/spec/fixtures/github/contents_python_repo.json
@@ -0,0 +1,450 @@
+[
+ {
+ "name": ".codeclimate.yml",
+ "path": ".codeclimate.yml",
+ "sha": "6393602fac96cfe31d64f89476014124b4a13b85",
+ "size": 416,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.codeclimate.yml?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.codeclimate.yml",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/6393602fac96cfe31d64f89476014124b4a13b85",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/.codeclimate.yml",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.codeclimate.yml?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/6393602fac96cfe31d64f89476014124b4a13b85",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.codeclimate.yml"
+ }
+ },
+ {
+ "name": ".coveragerc",
+ "path": ".coveragerc",
+ "sha": "be7fdc86067d0924f3e1e92c1a3ed92d9486fcbb",
+ "size": 646,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.coveragerc?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.coveragerc",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/be7fdc86067d0924f3e1e92c1a3ed92d9486fcbb",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/.coveragerc",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.coveragerc?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/be7fdc86067d0924f3e1e92c1a3ed92d9486fcbb",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.coveragerc"
+ }
+ },
+ {
+ "name": ".csslintrc",
+ "path": ".csslintrc",
+ "sha": "aacba956e5bbede1c195ce554fcad3e200b24ff8",
+ "size": 107,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.csslintrc?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.csslintrc",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/aacba956e5bbede1c195ce554fcad3e200b24ff8",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/.csslintrc",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.csslintrc?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/aacba956e5bbede1c195ce554fcad3e200b24ff8",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.csslintrc"
+ }
+ },
+ {
+ "name": ".env.example",
+ "path": ".env.example",
+ "sha": "d9f599b33ecd834ea88979dcc3daf4fcafacf4e7",
+ "size": 2617,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.env.example?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.env.example",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/d9f599b33ecd834ea88979dcc3daf4fcafacf4e7",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/.env.example",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.env.example?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/d9f599b33ecd834ea88979dcc3daf4fcafacf4e7",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.env.example"
+ }
+ },
+ {
+ "name": ".eslintignore",
+ "path": ".eslintignore",
+ "sha": "96212a3593bac8c93f624b77185a8d11018efd96",
+ "size": 16,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.eslintignore?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.eslintignore",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/96212a3593bac8c93f624b77185a8d11018efd96",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/.eslintignore",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.eslintignore?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/96212a3593bac8c93f624b77185a8d11018efd96",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.eslintignore"
+ }
+ },
+ {
+ "name": ".eslintrc.yml",
+ "path": ".eslintrc.yml",
+ "sha": "a6a0ce9c44238e06ff55ca335a66a4e16810da38",
+ "size": 6056,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.eslintrc.yml?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.eslintrc.yml",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/a6a0ce9c44238e06ff55ca335a66a4e16810da38",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/.eslintrc.yml",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.eslintrc.yml?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/a6a0ce9c44238e06ff55ca335a66a4e16810da38",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.eslintrc.yml"
+ }
+ },
+ {
+ "name": ".gitignore",
+ "path": ".gitignore",
+ "sha": "93923ac3a463bd17d0aefca2de9d2810f243d747",
+ "size": 1073,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.gitignore?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.gitignore",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/93923ac3a463bd17d0aefca2de9d2810f243d747",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/.gitignore",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.gitignore?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/93923ac3a463bd17d0aefca2de9d2810f243d747",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.gitignore"
+ }
+ },
+ {
+ "name": "LICENSE.md",
+ "path": "LICENSE.md",
+ "sha": "8dada3edaf50dbc082c9a125058f25def75e625a",
+ "size": 11357,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/LICENSE.md?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/LICENSE.md",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/8dada3edaf50dbc082c9a125058f25def75e625a",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/LICENSE.md",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/LICENSE.md?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/8dada3edaf50dbc082c9a125058f25def75e625a",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/LICENSE.md"
+ }
+ },
+ {
+ "name": "Procfile",
+ "path": "Procfile",
+ "sha": "72e4ef1be7c64eb0f874344bc8a6cf859bd39e00",
+ "size": 26,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/Procfile?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/Procfile",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/72e4ef1be7c64eb0f874344bc8a6cf859bd39e00",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/Procfile",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/Procfile?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/72e4ef1be7c64eb0f874344bc8a6cf859bd39e00",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/Procfile"
+ }
+ },
+ {
+ "name": "README.md",
+ "path": "README.md",
+ "sha": "01aae7d562fe164d2cee644e8ef5fba82d2b8e81",
+ "size": 1589,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/README.md?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/README.md",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/01aae7d562fe164d2cee644e8ef5fba82d2b8e81",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/README.md",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/README.md?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/01aae7d562fe164d2cee644e8ef5fba82d2b8e81",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/README.md"
+ }
+ },
+ {
+ "name": "Vagrantfile.example",
+ "path": "Vagrantfile.example",
+ "sha": "54be29ea9e1e2ecdbfa642656cded8b3cb85c910",
+ "size": 4329,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/Vagrantfile.example?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/Vagrantfile.example",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/54be29ea9e1e2ecdbfa642656cded8b3cb85c910",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/Vagrantfile.example",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/Vagrantfile.example?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/54be29ea9e1e2ecdbfa642656cded8b3cb85c910",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/Vagrantfile.example"
+ }
+ },
+ {
+ "name": "app",
+ "path": "app",
+ "sha": "f9e84e24364972f3aa4f92b869a622db1f260fa1",
+ "size": 0,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/app?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/app",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/f9e84e24364972f3aa4f92b869a622db1f260fa1",
+ "download_url": null,
+ "type": "dir",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/app?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/f9e84e24364972f3aa4f92b869a622db1f260fa1",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/app"
+ }
+ },
+ {
+ "name": "build_scripts",
+ "path": "build_scripts",
+ "sha": "be8e80f054e47f0c9a6fc9cfe5061346c6f8b2d0",
+ "size": 0,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/build_scripts?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/build_scripts",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/be8e80f054e47f0c9a6fc9cfe5061346c6f8b2d0",
+ "download_url": null,
+ "type": "dir",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/build_scripts?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/be8e80f054e47f0c9a6fc9cfe5061346c6f8b2d0",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/build_scripts"
+ }
+ },
+ {
+ "name": "celery_worker.py",
+ "path": "celery_worker.py",
+ "sha": "c84c73c1f1c1aa42550a08ae4f32dc955ced5f18",
+ "size": 279,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/celery_worker.py?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/celery_worker.py",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/c84c73c1f1c1aa42550a08ae4f32dc955ced5f18",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/celery_worker.py",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/celery_worker.py?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/c84c73c1f1c1aa42550a08ae4f32dc955ced5f18",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/celery_worker.py"
+ }
+ },
+ {
+ "name": "config.py",
+ "path": "config.py",
+ "sha": "2886556fc4844e708472a99a85b42b4f5b51d509",
+ "size": 8250,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/config.py?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/config.py",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/2886556fc4844e708472a99a85b42b4f5b51d509",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/config.py",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/config.py?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/2886556fc4844e708472a99a85b42b4f5b51d509",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/config.py"
+ }
+ },
+ {
+ "name": "crontab",
+ "path": "crontab",
+ "sha": "1e2c1da613e8272df6ece759565524c93bc76780",
+ "size": 300,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/crontab?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/crontab",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/1e2c1da613e8272df6ece759565524c93bc76780",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/crontab",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/crontab?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/1e2c1da613e8272df6ece759565524c93bc76780",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/crontab"
+ }
+ },
+ {
+ "name": "data",
+ "path": "data",
+ "sha": "7bceca86ff0e88cb53c8828d441f5e0725776395",
+ "size": 0,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/data?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/data",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/7bceca86ff0e88cb53c8828d441f5e0725776395",
+ "download_url": null,
+ "type": "dir",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/data?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/7bceca86ff0e88cb53c8828d441f5e0725776395",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/data"
+ }
+ },
+ {
+ "name": "gunicorn_config.py",
+ "path": "gunicorn_config.py",
+ "sha": "7b1a455133c2e78611550e45e8d2072d5c5c4ad7",
+ "size": 2504,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/gunicorn_config.py?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/gunicorn_config.py",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/7b1a455133c2e78611550e45e8d2072d5c5c4ad7",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/gunicorn_config.py",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/gunicorn_config.py?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/7b1a455133c2e78611550e45e8d2072d5c5c4ad7",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/gunicorn_config.py"
+ }
+ },
+ {
+ "name": "jobs.py",
+ "path": "jobs.py",
+ "sha": "79f2957e2c94e44786f6ca3dfc7384aaceb80c0a",
+ "size": 6213,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/jobs.py?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/jobs.py",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/79f2957e2c94e44786f6ca3dfc7384aaceb80c0a",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/jobs.py",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/jobs.py?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/79f2957e2c94e44786f6ca3dfc7384aaceb80c0a",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/jobs.py"
+ }
+ },
+ {
+ "name": "magic",
+ "path": "magic",
+ "sha": "6342094c1d4b1af948867ffba67cf0b866e5613c",
+ "size": 659195,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/magic?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/magic",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/6342094c1d4b1af948867ffba67cf0b866e5613c",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/magic",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/magic?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/6342094c1d4b1af948867ffba67cf0b866e5613c",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/magic"
+ }
+ },
+ {
+ "name": "manage.py",
+ "path": "manage.py",
+ "sha": "a0b80d4c7b5fd7e50d6dcb5bcbdcd995b8da27f0",
+ "size": 15323,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/manage.py?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/manage.py",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/a0b80d4c7b5fd7e50d6dcb5bcbdcd995b8da27f0",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/manage.py",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/manage.py?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/a0b80d4c7b5fd7e50d6dcb5bcbdcd995b8da27f0",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/manage.py"
+ }
+ },
+ {
+ "name": "migrations",
+ "path": "migrations",
+ "sha": "da206a9809330d01f4800718bca2a20c05038b44",
+ "size": 0,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/migrations?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/migrations",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/da206a9809330d01f4800718bca2a20c05038b44",
+ "download_url": null,
+ "type": "dir",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/migrations?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/da206a9809330d01f4800718bca2a20c05038b44",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/migrations"
+ }
+ },
+ {
+ "name": "requirements",
+ "path": "requirements",
+ "sha": "330d411ac0a8b7e58ea377f02c04145663ddde7c",
+ "size": 0,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/requirements?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/requirements",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/330d411ac0a8b7e58ea377f02c04145663ddde7c",
+ "download_url": null,
+ "type": "dir",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/requirements?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/330d411ac0a8b7e58ea377f02c04145663ddde7c",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/requirements"
+ }
+ },
+ {
+ "name": "requirements.txt",
+ "path": "requirements.txt",
+ "sha": "88b4e0a1c8093fae2b4fa52534035f9f85ed0956",
+ "size": 2433,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/requirements.txt?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/requirements.txt",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/88b4e0a1c8093fae2b4fa52534035f9f85ed0956",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/requirements.txt",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/requirements.txt?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/88b4e0a1c8093fae2b4fa52534035f9f85ed0956",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/requirements.txt"
+ }
+ },
+ {
+ "name": "setup.py",
+ "path": "setup.py",
+ "sha": "d429264c8c2f0f306a422900c2f41123e07c31b4",
+ "size": 2433,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/setup.py?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/setup.py",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/d429264c8c2f0f306a422900c2f41123e07c31b4",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/setup.py",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/setup.py?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/d429264c8c2f0f306a422900c2f41123e07c31b4",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/setup.py"
+ }
+ },
+ {
+ "name": "tests",
+ "path": "tests",
+ "sha": "88b4e0a1c8093fae2b4fa52534035f9f85ed0956",
+ "size": 0,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/tests?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/tests",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/88b4e0a1c8093fae2b4fa52534035f9f85ed0956",
+ "download_url": null,
+ "type": "dir",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/tests?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/88b4e0a1c8093fae2b4fa52534035f9f85ed0956",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/tests"
+ }
+ },
+ {
+ "name": "todo.txt",
+ "path": "todo.txt",
+ "sha": "3e369beef1c9e64f0c10735d35aa8ad755daddc6",
+ "size": 1147,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/todo.txt?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/todo.txt",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/3e369beef1c9e64f0c10735d35aa8ad755daddc6",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/todo.txt",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/todo.txt?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/3e369beef1c9e64f0c10735d35aa8ad755daddc6",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/todo.txt"
+ }
+ },
+ {
+ "name": "update_definitions.sh",
+ "path": "update_definitions.sh",
+ "sha": "fbde266ea5ebd519b94d18f8f78ab825b02766df",
+ "size": 7877,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/update_definitions.sh?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/update_definitions.sh",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/fbde266ea5ebd519b94d18f8f78ab825b02766df",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/update_definitions.sh",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/update_definitions.sh?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/fbde266ea5ebd519b94d18f8f78ab825b02766df",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/update_definitions.sh"
+ }
+ }
+]
diff --git a/uv/spec/fixtures/github/contents_python_requirements_folder.json b/uv/spec/fixtures/github/contents_python_requirements_folder.json
new file mode 100644
index 00000000000..d64818146a4
--- /dev/null
+++ b/uv/spec/fixtures/github/contents_python_requirements_folder.json
@@ -0,0 +1,130 @@
+[
+ {
+ "name": "coverage.in",
+ "path": "requirements/coverage.in",
+ "sha": "bcc1ab41d4c1861056758e95907c29412c2f1cae",
+ "size": 27,
+ "url": "https://api.github.com/repos/HypothesisWorks/hypothesis/contents/requirements/coverage.in?ref=master",
+ "html_url": "https://github.com/HypothesisWorks/hypothesis/blob/master/requirements/coverage.in",
+ "git_url": "https://api.github.com/repos/HypothesisWorks/hypothesis/git/blobs/bcc1ab41d4c1861056758e95907c29412c2f1cae",
+ "download_url": "https://raw.githubusercontent.com/HypothesisWorks/hypothesis/master/requirements/coverage.in",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/HypothesisWorks/hypothesis/contents/requirements/coverage.in?ref=master",
+ "git": "https://api.github.com/repos/HypothesisWorks/hypothesis/git/blobs/bcc1ab41d4c1861056758e95907c29412c2f1cae",
+ "html": "https://github.com/HypothesisWorks/hypothesis/blob/master/requirements/coverage.in"
+ }
+ },
+ {
+ "name": "coverage.txt",
+ "path": "requirements/coverage.txt",
+ "sha": "5c991f7f52b7736c7aea8083868ef7aa057eda28",
+ "size": 295,
+ "url": "https://api.github.com/repos/HypothesisWorks/hypothesis/contents/requirements/coverage.txt?ref=master",
+ "html_url": "https://github.com/HypothesisWorks/hypothesis/blob/master/requirements/coverage.txt",
+ "git_url": "https://api.github.com/repos/HypothesisWorks/hypothesis/git/blobs/5c991f7f52b7736c7aea8083868ef7aa057eda28",
+ "download_url": "https://raw.githubusercontent.com/HypothesisWorks/hypothesis/master/requirements/coverage.txt",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/HypothesisWorks/hypothesis/contents/requirements/coverage.txt?ref=master",
+ "git": "https://api.github.com/repos/HypothesisWorks/hypothesis/git/blobs/5c991f7f52b7736c7aea8083868ef7aa057eda28",
+ "html": "https://github.com/HypothesisWorks/hypothesis/blob/master/requirements/coverage.txt"
+ }
+ },
+ {
+ "name": "test.in",
+ "path": "requirements/test.in",
+ "sha": "5b780009d805a6b9fd9e499528039dc4cf59db4d",
+ "size": 37,
+ "url": "https://api.github.com/repos/HypothesisWorks/hypothesis/contents/requirements/test.in?ref=master",
+ "html_url": "https://github.com/HypothesisWorks/hypothesis/blob/master/requirements/test.in",
+ "git_url": "https://api.github.com/repos/HypothesisWorks/hypothesis/git/blobs/5b780009d805a6b9fd9e499528039dc4cf59db4d",
+ "download_url": "https://raw.githubusercontent.com/HypothesisWorks/hypothesis/master/requirements/test.in",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/HypothesisWorks/hypothesis/contents/requirements/test.in?ref=master",
+ "git": "https://api.github.com/repos/HypothesisWorks/hypothesis/git/blobs/5b780009d805a6b9fd9e499528039dc4cf59db4d",
+ "html": "https://github.com/HypothesisWorks/hypothesis/blob/master/requirements/test.in"
+ }
+ },
+ {
+ "name": "test.txt",
+ "path": "requirements/test.txt",
+ "sha": "3d16646e3a2c7ea587b3283d0714bc299c2d0d76",
+ "size": 561,
+ "url": "https://api.github.com/repos/HypothesisWorks/hypothesis/contents/requirements/test.txt?ref=master",
+ "html_url": "https://github.com/HypothesisWorks/hypothesis/blob/master/requirements/test.txt",
+ "git_url": "https://api.github.com/repos/HypothesisWorks/hypothesis/git/blobs/3d16646e3a2c7ea587b3283d0714bc299c2d0d76",
+ "download_url": "https://raw.githubusercontent.com/HypothesisWorks/hypothesis/master/requirements/test.txt",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/HypothesisWorks/hypothesis/contents/requirements/test.txt?ref=master",
+ "git": "https://api.github.com/repos/HypothesisWorks/hypothesis/git/blobs/3d16646e3a2c7ea587b3283d0714bc299c2d0d76",
+ "html": "https://github.com/HypothesisWorks/hypothesis/blob/master/requirements/test.txt"
+ }
+ },
+ {
+ "name": "tools.in",
+ "path": "requirements/tools.in",
+ "sha": "c55c0089c06bc3a9820369e00639caa8435a0205",
+ "size": 153,
+ "url": "https://api.github.com/repos/HypothesisWorks/hypothesis/contents/requirements/tools.in?ref=master",
+ "html_url": "https://github.com/HypothesisWorks/hypothesis/blob/master/requirements/tools.in",
+ "git_url": "https://api.github.com/repos/HypothesisWorks/hypothesis/git/blobs/c55c0089c06bc3a9820369e00639caa8435a0205",
+ "download_url": "https://raw.githubusercontent.com/HypothesisWorks/hypothesis/master/requirements/tools.in",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/HypothesisWorks/hypothesis/contents/requirements/tools.in?ref=master",
+ "git": "https://api.github.com/repos/HypothesisWorks/hypothesis/git/blobs/c55c0089c06bc3a9820369e00639caa8435a0205",
+ "html": "https://github.com/HypothesisWorks/hypothesis/blob/master/requirements/tools.in"
+ }
+ },
+ {
+ "name": "tools.txt",
+ "path": "requirements/tools.txt",
+ "sha": "984f8fff8331f8e4d245a4291528a53a40f07c59",
+ "size": 2490,
+ "url": "https://api.github.com/repos/HypothesisWorks/hypothesis/contents/requirements/tools.txt?ref=master",
+ "html_url": "https://github.com/HypothesisWorks/hypothesis/blob/master/requirements/tools.txt",
+ "git_url": "https://api.github.com/repos/HypothesisWorks/hypothesis/git/blobs/984f8fff8331f8e4d245a4291528a53a40f07c59",
+ "download_url": "https://raw.githubusercontent.com/HypothesisWorks/hypothesis/master/requirements/tools.txt",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/HypothesisWorks/hypothesis/contents/requirements/tools.txt?ref=master",
+ "git": "https://api.github.com/repos/HypothesisWorks/hypothesis/git/blobs/984f8fff8331f8e4d245a4291528a53a40f07c59",
+ "html": "https://github.com/HypothesisWorks/hypothesis/blob/master/requirements/tools.txt"
+ }
+ },
+ {
+ "name": "typing.in",
+ "path": "requirements/typing.in",
+ "sha": "c997f364b496e17a0e44cf0e9d58835a02c16bdb",
+ "size": 7,
+ "url": "https://api.github.com/repos/HypothesisWorks/hypothesis/contents/requirements/typing.in?ref=master",
+ "html_url": "https://github.com/HypothesisWorks/hypothesis/blob/master/requirements/typing.in",
+ "git_url": "https://api.github.com/repos/HypothesisWorks/hypothesis/git/blobs/c997f364b496e17a0e44cf0e9d58835a02c16bdb",
+ "download_url": "https://raw.githubusercontent.com/HypothesisWorks/hypothesis/master/requirements/typing.in",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/HypothesisWorks/hypothesis/contents/requirements/typing.in?ref=master",
+ "git": "https://api.github.com/repos/HypothesisWorks/hypothesis/git/blobs/c997f364b496e17a0e44cf0e9d58835a02c16bdb",
+ "html": "https://github.com/HypothesisWorks/hypothesis/blob/master/requirements/typing.in"
+ }
+ },
+ {
+ "name": "typing.txt",
+ "path": "requirements/typing.txt",
+ "sha": "15a2c7ee76c23710281d57865320a3358d638dc5",
+ "size": 160,
+ "url": "https://api.github.com/repos/HypothesisWorks/hypothesis/contents/requirements/typing.txt?ref=master",
+ "html_url": "https://github.com/HypothesisWorks/hypothesis/blob/master/requirements/typing.txt",
+ "git_url": "https://api.github.com/repos/HypothesisWorks/hypothesis/git/blobs/15a2c7ee76c23710281d57865320a3358d638dc5",
+ "download_url": "https://raw.githubusercontent.com/HypothesisWorks/hypothesis/master/requirements/typing.txt",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/HypothesisWorks/hypothesis/contents/requirements/typing.txt?ref=master",
+ "git": "https://api.github.com/repos/HypothesisWorks/hypothesis/git/blobs/15a2c7ee76c23710281d57865320a3358d638dc5",
+ "html": "https://github.com/HypothesisWorks/hypothesis/blob/master/requirements/typing.txt"
+ }
+ }
+]
diff --git a/uv/spec/fixtures/github/contents_python_with_conf.json b/uv/spec/fixtures/github/contents_python_with_conf.json
new file mode 100644
index 00000000000..f1f2fa2636a
--- /dev/null
+++ b/uv/spec/fixtures/github/contents_python_with_conf.json
@@ -0,0 +1,450 @@
+[
+ {
+ "name": ".codeclimate.yml",
+ "path": ".codeclimate.yml",
+ "sha": "6393602fac96cfe31d64f89476014124b4a13b85",
+ "size": 416,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.codeclimate.yml?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.codeclimate.yml",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/6393602fac96cfe31d64f89476014124b4a13b85",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/.codeclimate.yml",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.codeclimate.yml?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/6393602fac96cfe31d64f89476014124b4a13b85",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.codeclimate.yml"
+ }
+ },
+ {
+ "name": ".coveragerc",
+ "path": ".coveragerc",
+ "sha": "be7fdc86067d0924f3e1e92c1a3ed92d9486fcbb",
+ "size": 646,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.coveragerc?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.coveragerc",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/be7fdc86067d0924f3e1e92c1a3ed92d9486fcbb",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/.coveragerc",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.coveragerc?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/be7fdc86067d0924f3e1e92c1a3ed92d9486fcbb",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.coveragerc"
+ }
+ },
+ {
+ "name": ".csslintrc",
+ "path": ".csslintrc",
+ "sha": "aacba956e5bbede1c195ce554fcad3e200b24ff8",
+ "size": 107,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.csslintrc?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.csslintrc",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/aacba956e5bbede1c195ce554fcad3e200b24ff8",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/.csslintrc",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.csslintrc?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/aacba956e5bbede1c195ce554fcad3e200b24ff8",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.csslintrc"
+ }
+ },
+ {
+ "name": ".env.example",
+ "path": ".env.example",
+ "sha": "d9f599b33ecd834ea88979dcc3daf4fcafacf4e7",
+ "size": 2617,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.env.example?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.env.example",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/d9f599b33ecd834ea88979dcc3daf4fcafacf4e7",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/.env.example",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.env.example?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/d9f599b33ecd834ea88979dcc3daf4fcafacf4e7",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.env.example"
+ }
+ },
+ {
+ "name": ".eslintignore",
+ "path": ".eslintignore",
+ "sha": "96212a3593bac8c93f624b77185a8d11018efd96",
+ "size": 16,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.eslintignore?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.eslintignore",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/96212a3593bac8c93f624b77185a8d11018efd96",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/.eslintignore",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.eslintignore?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/96212a3593bac8c93f624b77185a8d11018efd96",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.eslintignore"
+ }
+ },
+ {
+ "name": ".eslintrc.yml",
+ "path": ".eslintrc.yml",
+ "sha": "a6a0ce9c44238e06ff55ca335a66a4e16810da38",
+ "size": 6056,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.eslintrc.yml?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.eslintrc.yml",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/a6a0ce9c44238e06ff55ca335a66a4e16810da38",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/.eslintrc.yml",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.eslintrc.yml?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/a6a0ce9c44238e06ff55ca335a66a4e16810da38",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.eslintrc.yml"
+ }
+ },
+ {
+ "name": ".gitignore",
+ "path": ".gitignore",
+ "sha": "93923ac3a463bd17d0aefca2de9d2810f243d747",
+ "size": 1073,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.gitignore?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.gitignore",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/93923ac3a463bd17d0aefca2de9d2810f243d747",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/.gitignore",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.gitignore?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/93923ac3a463bd17d0aefca2de9d2810f243d747",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.gitignore"
+ }
+ },
+ {
+ "name": ".python-version",
+ "path": ".python-version",
+ "sha": "87ce492908ab2362771f27134bab4a075348a8f3",
+ "size": 6,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.python-version?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.python-version",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/87ce492908ab2362771f27134bab4a075348a8f3",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/.python-version",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.python-version?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/87ce492908ab2362771f27134bab4a075348a8f3",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.python-version"
+ }
+ },
+ {
+ "name": "LICENSE.md",
+ "path": "LICENSE.md",
+ "sha": "8dada3edaf50dbc082c9a125058f25def75e625a",
+ "size": 11357,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/LICENSE.md?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/LICENSE.md",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/8dada3edaf50dbc082c9a125058f25def75e625a",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/LICENSE.md",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/LICENSE.md?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/8dada3edaf50dbc082c9a125058f25def75e625a",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/LICENSE.md"
+ }
+ },
+ {
+ "name": "Procfile",
+ "path": "Procfile",
+ "sha": "72e4ef1be7c64eb0f874344bc8a6cf859bd39e00",
+ "size": 26,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/Procfile?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/Procfile",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/72e4ef1be7c64eb0f874344bc8a6cf859bd39e00",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/Procfile",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/Procfile?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/72e4ef1be7c64eb0f874344bc8a6cf859bd39e00",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/Procfile"
+ }
+ },
+ {
+ "name": "README.md",
+ "path": "README.md",
+ "sha": "01aae7d562fe164d2cee644e8ef5fba82d2b8e81",
+ "size": 1589,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/README.md?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/README.md",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/01aae7d562fe164d2cee644e8ef5fba82d2b8e81",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/README.md",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/README.md?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/01aae7d562fe164d2cee644e8ef5fba82d2b8e81",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/README.md"
+ }
+ },
+ {
+ "name": "Vagrantfile.example",
+ "path": "Vagrantfile.example",
+ "sha": "54be29ea9e1e2ecdbfa642656cded8b3cb85c910",
+ "size": 4329,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/Vagrantfile.example?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/Vagrantfile.example",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/54be29ea9e1e2ecdbfa642656cded8b3cb85c910",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/Vagrantfile.example",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/Vagrantfile.example?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/54be29ea9e1e2ecdbfa642656cded8b3cb85c910",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/Vagrantfile.example"
+ }
+ },
+ {
+ "name": "app",
+ "path": "app",
+ "sha": "f9e84e24364972f3aa4f92b869a622db1f260fa1",
+ "size": 0,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/app?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/app",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/f9e84e24364972f3aa4f92b869a622db1f260fa1",
+ "download_url": null,
+ "type": "dir",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/app?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/f9e84e24364972f3aa4f92b869a622db1f260fa1",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/app"
+ }
+ },
+ {
+ "name": "build_scripts",
+ "path": "build_scripts",
+ "sha": "be8e80f054e47f0c9a6fc9cfe5061346c6f8b2d0",
+ "size": 0,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/build_scripts?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/build_scripts",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/be8e80f054e47f0c9a6fc9cfe5061346c6f8b2d0",
+ "download_url": null,
+ "type": "dir",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/build_scripts?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/be8e80f054e47f0c9a6fc9cfe5061346c6f8b2d0",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/build_scripts"
+ }
+ },
+ {
+ "name": "celery_worker.py",
+ "path": "celery_worker.py",
+ "sha": "c84c73c1f1c1aa42550a08ae4f32dc955ced5f18",
+ "size": 279,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/celery_worker.py?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/celery_worker.py",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/c84c73c1f1c1aa42550a08ae4f32dc955ced5f18",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/celery_worker.py",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/celery_worker.py?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/c84c73c1f1c1aa42550a08ae4f32dc955ced5f18",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/celery_worker.py"
+ }
+ },
+ {
+ "name": "config.py",
+ "path": "config.py",
+ "sha": "2886556fc4844e708472a99a85b42b4f5b51d509",
+ "size": 8250,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/config.py?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/config.py",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/2886556fc4844e708472a99a85b42b4f5b51d509",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/config.py",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/config.py?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/2886556fc4844e708472a99a85b42b4f5b51d509",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/config.py"
+ }
+ },
+ {
+ "name": "crontab",
+ "path": "crontab",
+ "sha": "1e2c1da613e8272df6ece759565524c93bc76780",
+ "size": 300,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/crontab?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/crontab",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/1e2c1da613e8272df6ece759565524c93bc76780",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/crontab",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/crontab?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/1e2c1da613e8272df6ece759565524c93bc76780",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/crontab"
+ }
+ },
+ {
+ "name": "data",
+ "path": "data",
+ "sha": "7bceca86ff0e88cb53c8828d441f5e0725776395",
+ "size": 0,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/data?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/data",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/7bceca86ff0e88cb53c8828d441f5e0725776395",
+ "download_url": null,
+ "type": "dir",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/data?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/7bceca86ff0e88cb53c8828d441f5e0725776395",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/data"
+ }
+ },
+ {
+ "name": "gunicorn_config.py",
+ "path": "gunicorn_config.py",
+ "sha": "7b1a455133c2e78611550e45e8d2072d5c5c4ad7",
+ "size": 2504,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/gunicorn_config.py?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/gunicorn_config.py",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/7b1a455133c2e78611550e45e8d2072d5c5c4ad7",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/gunicorn_config.py",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/gunicorn_config.py?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/7b1a455133c2e78611550e45e8d2072d5c5c4ad7",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/gunicorn_config.py"
+ }
+ },
+ {
+ "name": "jobs.py",
+ "path": "jobs.py",
+ "sha": "79f2957e2c94e44786f6ca3dfc7384aaceb80c0a",
+ "size": 6213,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/jobs.py?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/jobs.py",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/79f2957e2c94e44786f6ca3dfc7384aaceb80c0a",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/jobs.py",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/jobs.py?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/79f2957e2c94e44786f6ca3dfc7384aaceb80c0a",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/jobs.py"
+ }
+ },
+ {
+ "name": "magic",
+ "path": "magic",
+ "sha": "6342094c1d4b1af948867ffba67cf0b866e5613c",
+ "size": 659195,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/magic?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/magic",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/6342094c1d4b1af948867ffba67cf0b866e5613c",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/magic",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/magic?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/6342094c1d4b1af948867ffba67cf0b866e5613c",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/magic"
+ }
+ },
+ {
+ "name": "manage.py",
+ "path": "manage.py",
+ "sha": "a0b80d4c7b5fd7e50d6dcb5bcbdcd995b8da27f0",
+ "size": 15323,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/manage.py?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/manage.py",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/a0b80d4c7b5fd7e50d6dcb5bcbdcd995b8da27f0",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/manage.py",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/manage.py?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/a0b80d4c7b5fd7e50d6dcb5bcbdcd995b8da27f0",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/manage.py"
+ }
+ },
+ {
+ "name": "migrations",
+ "path": "migrations",
+ "sha": "da206a9809330d01f4800718bca2a20c05038b44",
+ "size": 0,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/migrations?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/migrations",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/da206a9809330d01f4800718bca2a20c05038b44",
+ "download_url": null,
+ "type": "dir",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/migrations?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/da206a9809330d01f4800718bca2a20c05038b44",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/migrations"
+ }
+ },
+ {
+ "name": "pip.conf",
+ "path": "pip.conf",
+ "sha": "d429264c8c2f0f306a422900c2f41123e07c31b4",
+ "size": 2433,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/pip.conf?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/pip.conf",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/d429264c8c2f0f306a422900c2f41123e07c31b4",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/pip.conf",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/pip.conf?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/d429264c8c2f0f306a422900c2f41123e07c31b4",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/pip.conf"
+ }
+ },
+ {
+ "name": "requirements.txt",
+ "path": "requirements.txt",
+ "sha": "88b4e0a1c8093fae2b4fa52534035f9f85ed0956",
+ "size": 2433,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/requirements.txt?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/requirements.txt",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/88b4e0a1c8093fae2b4fa52534035f9f85ed0956",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/requirements.txt",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/requirements.txt?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/88b4e0a1c8093fae2b4fa52534035f9f85ed0956",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/requirements.txt"
+ }
+ },
+ {
+ "name": "tests",
+ "path": "tests",
+ "sha": "88b4e0a1c8093fae2b4fa52534035f9f85ed0956",
+ "size": 0,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/tests?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/tests",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/88b4e0a1c8093fae2b4fa52534035f9f85ed0956",
+ "download_url": null,
+ "type": "dir",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/tests?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/88b4e0a1c8093fae2b4fa52534035f9f85ed0956",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/tests"
+ }
+ },
+ {
+ "name": "todo.txt",
+ "path": "todo.txt",
+ "sha": "3e369beef1c9e64f0c10735d35aa8ad755daddc6",
+ "size": 1147,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/todo.txt?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/todo.txt",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/3e369beef1c9e64f0c10735d35aa8ad755daddc6",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/todo.txt",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/todo.txt?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/3e369beef1c9e64f0c10735d35aa8ad755daddc6",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/todo.txt"
+ }
+ },
+ {
+ "name": "update_definitions.sh",
+ "path": "update_definitions.sh",
+ "sha": "fbde266ea5ebd519b94d18f8f78ab825b02766df",
+ "size": 7877,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/update_definitions.sh?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/update_definitions.sh",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/fbde266ea5ebd519b94d18f8f78ab825b02766df",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/update_definitions.sh",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/update_definitions.sh?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/fbde266ea5ebd519b94d18f8f78ab825b02766df",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/update_definitions.sh"
+ }
+ }
+]
diff --git a/uv/spec/fixtures/github/contents_python_with_setup_cfg.json b/uv/spec/fixtures/github/contents_python_with_setup_cfg.json
new file mode 100644
index 00000000000..7744004e454
--- /dev/null
+++ b/uv/spec/fixtures/github/contents_python_with_setup_cfg.json
@@ -0,0 +1,434 @@
+[
+ {
+ "name": ".codeclimate.yml",
+ "path": ".codeclimate.yml",
+ "sha": "6393602fac96cfe31d64f89476014124b4a13b85",
+ "size": 416,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.codeclimate.yml?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.codeclimate.yml",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/6393602fac96cfe31d64f89476014124b4a13b85",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/.codeclimate.yml",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.codeclimate.yml?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/6393602fac96cfe31d64f89476014124b4a13b85",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.codeclimate.yml"
+ }
+ },
+ {
+ "name": ".coveragerc",
+ "path": ".coveragerc",
+ "sha": "be7fdc86067d0924f3e1e92c1a3ed92d9486fcbb",
+ "size": 646,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.coveragerc?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.coveragerc",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/be7fdc86067d0924f3e1e92c1a3ed92d9486fcbb",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/.coveragerc",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.coveragerc?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/be7fdc86067d0924f3e1e92c1a3ed92d9486fcbb",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.coveragerc"
+ }
+ },
+ {
+ "name": ".csslintrc",
+ "path": ".csslintrc",
+ "sha": "aacba956e5bbede1c195ce554fcad3e200b24ff8",
+ "size": 107,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.csslintrc?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.csslintrc",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/aacba956e5bbede1c195ce554fcad3e200b24ff8",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/.csslintrc",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.csslintrc?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/aacba956e5bbede1c195ce554fcad3e200b24ff8",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.csslintrc"
+ }
+ },
+ {
+ "name": ".env.example",
+ "path": ".env.example",
+ "sha": "d9f599b33ecd834ea88979dcc3daf4fcafacf4e7",
+ "size": 2617,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.env.example?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.env.example",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/d9f599b33ecd834ea88979dcc3daf4fcafacf4e7",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/.env.example",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.env.example?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/d9f599b33ecd834ea88979dcc3daf4fcafacf4e7",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.env.example"
+ }
+ },
+ {
+ "name": ".eslintignore",
+ "path": ".eslintignore",
+ "sha": "96212a3593bac8c93f624b77185a8d11018efd96",
+ "size": 16,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.eslintignore?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.eslintignore",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/96212a3593bac8c93f624b77185a8d11018efd96",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/.eslintignore",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.eslintignore?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/96212a3593bac8c93f624b77185a8d11018efd96",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.eslintignore"
+ }
+ },
+ {
+ "name": ".eslintrc.yml",
+ "path": ".eslintrc.yml",
+ "sha": "a6a0ce9c44238e06ff55ca335a66a4e16810da38",
+ "size": 6056,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.eslintrc.yml?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.eslintrc.yml",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/a6a0ce9c44238e06ff55ca335a66a4e16810da38",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/.eslintrc.yml",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.eslintrc.yml?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/a6a0ce9c44238e06ff55ca335a66a4e16810da38",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.eslintrc.yml"
+ }
+ },
+ {
+ "name": ".gitignore",
+ "path": ".gitignore",
+ "sha": "93923ac3a463bd17d0aefca2de9d2810f243d747",
+ "size": 1073,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.gitignore?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.gitignore",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/93923ac3a463bd17d0aefca2de9d2810f243d747",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/.gitignore",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/.gitignore?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/93923ac3a463bd17d0aefca2de9d2810f243d747",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/.gitignore"
+ }
+ },
+ {
+ "name": "LICENSE.md",
+ "path": "LICENSE.md",
+ "sha": "8dada3edaf50dbc082c9a125058f25def75e625a",
+ "size": 11357,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/LICENSE.md?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/LICENSE.md",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/8dada3edaf50dbc082c9a125058f25def75e625a",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/LICENSE.md",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/LICENSE.md?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/8dada3edaf50dbc082c9a125058f25def75e625a",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/LICENSE.md"
+ }
+ },
+ {
+ "name": "Procfile",
+ "path": "Procfile",
+ "sha": "72e4ef1be7c64eb0f874344bc8a6cf859bd39e00",
+ "size": 26,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/Procfile?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/Procfile",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/72e4ef1be7c64eb0f874344bc8a6cf859bd39e00",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/Procfile",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/Procfile?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/72e4ef1be7c64eb0f874344bc8a6cf859bd39e00",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/Procfile"
+ }
+ },
+ {
+ "name": "README.md",
+ "path": "README.md",
+ "sha": "01aae7d562fe164d2cee644e8ef5fba82d2b8e81",
+ "size": 1589,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/README.md?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/README.md",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/01aae7d562fe164d2cee644e8ef5fba82d2b8e81",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/README.md",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/README.md?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/01aae7d562fe164d2cee644e8ef5fba82d2b8e81",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/README.md"
+ }
+ },
+ {
+ "name": "Vagrantfile.example",
+ "path": "Vagrantfile.example",
+ "sha": "54be29ea9e1e2ecdbfa642656cded8b3cb85c910",
+ "size": 4329,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/Vagrantfile.example?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/Vagrantfile.example",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/54be29ea9e1e2ecdbfa642656cded8b3cb85c910",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/Vagrantfile.example",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/Vagrantfile.example?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/54be29ea9e1e2ecdbfa642656cded8b3cb85c910",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/Vagrantfile.example"
+ }
+ },
+ {
+ "name": "app",
+ "path": "app",
+ "sha": "f9e84e24364972f3aa4f92b869a622db1f260fa1",
+ "size": 0,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/app?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/app",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/f9e84e24364972f3aa4f92b869a622db1f260fa1",
+ "download_url": null,
+ "type": "dir",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/app?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/f9e84e24364972f3aa4f92b869a622db1f260fa1",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/app"
+ }
+ },
+ {
+ "name": "build_scripts",
+ "path": "build_scripts",
+ "sha": "be8e80f054e47f0c9a6fc9cfe5061346c6f8b2d0",
+ "size": 0,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/build_scripts?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/build_scripts",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/be8e80f054e47f0c9a6fc9cfe5061346c6f8b2d0",
+ "download_url": null,
+ "type": "dir",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/build_scripts?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/be8e80f054e47f0c9a6fc9cfe5061346c6f8b2d0",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/build_scripts"
+ }
+ },
+ {
+ "name": "celery_worker.py",
+ "path": "celery_worker.py",
+ "sha": "c84c73c1f1c1aa42550a08ae4f32dc955ced5f18",
+ "size": 279,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/celery_worker.py?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/celery_worker.py",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/c84c73c1f1c1aa42550a08ae4f32dc955ced5f18",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/celery_worker.py",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/celery_worker.py?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/c84c73c1f1c1aa42550a08ae4f32dc955ced5f18",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/celery_worker.py"
+ }
+ },
+ {
+ "name": "config.py",
+ "path": "config.py",
+ "sha": "2886556fc4844e708472a99a85b42b4f5b51d509",
+ "size": 8250,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/config.py?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/config.py",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/2886556fc4844e708472a99a85b42b4f5b51d509",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/config.py",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/config.py?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/2886556fc4844e708472a99a85b42b4f5b51d509",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/config.py"
+ }
+ },
+ {
+ "name": "crontab",
+ "path": "crontab",
+ "sha": "1e2c1da613e8272df6ece759565524c93bc76780",
+ "size": 300,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/crontab?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/crontab",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/1e2c1da613e8272df6ece759565524c93bc76780",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/crontab",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/crontab?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/1e2c1da613e8272df6ece759565524c93bc76780",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/crontab"
+ }
+ },
+ {
+ "name": "data",
+ "path": "data",
+ "sha": "7bceca86ff0e88cb53c8828d441f5e0725776395",
+ "size": 0,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/data?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/data",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/7bceca86ff0e88cb53c8828d441f5e0725776395",
+ "download_url": null,
+ "type": "dir",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/data?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/7bceca86ff0e88cb53c8828d441f5e0725776395",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/data"
+ }
+ },
+ {
+ "name": "gunicorn_config.py",
+ "path": "gunicorn_config.py",
+ "sha": "7b1a455133c2e78611550e45e8d2072d5c5c4ad7",
+ "size": 2504,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/gunicorn_config.py?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/gunicorn_config.py",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/7b1a455133c2e78611550e45e8d2072d5c5c4ad7",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/gunicorn_config.py",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/gunicorn_config.py?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/7b1a455133c2e78611550e45e8d2072d5c5c4ad7",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/gunicorn_config.py"
+ }
+ },
+ {
+ "name": "jobs.py",
+ "path": "jobs.py",
+ "sha": "79f2957e2c94e44786f6ca3dfc7384aaceb80c0a",
+ "size": 6213,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/jobs.py?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/jobs.py",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/79f2957e2c94e44786f6ca3dfc7384aaceb80c0a",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/jobs.py",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/jobs.py?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/79f2957e2c94e44786f6ca3dfc7384aaceb80c0a",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/jobs.py"
+ }
+ },
+ {
+ "name": "magic",
+ "path": "magic",
+ "sha": "6342094c1d4b1af948867ffba67cf0b866e5613c",
+ "size": 659195,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/magic?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/magic",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/6342094c1d4b1af948867ffba67cf0b866e5613c",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/magic",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/magic?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/6342094c1d4b1af948867ffba67cf0b866e5613c",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/magic"
+ }
+ },
+ {
+ "name": "manage.py",
+ "path": "manage.py",
+ "sha": "a0b80d4c7b5fd7e50d6dcb5bcbdcd995b8da27f0",
+ "size": 15323,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/manage.py?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/manage.py",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/a0b80d4c7b5fd7e50d6dcb5bcbdcd995b8da27f0",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/manage.py",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/manage.py?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/a0b80d4c7b5fd7e50d6dcb5bcbdcd995b8da27f0",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/manage.py"
+ }
+ },
+ {
+ "name": "migrations",
+ "path": "migrations",
+ "sha": "da206a9809330d01f4800718bca2a20c05038b44",
+ "size": 0,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/migrations?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/migrations",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/da206a9809330d01f4800718bca2a20c05038b44",
+ "download_url": null,
+ "type": "dir",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/migrations?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/da206a9809330d01f4800718bca2a20c05038b44",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/migrations"
+ }
+ },
+ {
+ "name": "setup.cfg",
+ "path": "setup.cfg",
+ "sha": "d429264c8c2f0f306a422900c2f41123e07c31b4",
+ "size": 2433,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/setup.cfg?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/setup.cfg",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/d429264c8c2f0f306a422900c2f41123e07c31b4",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/setup.cfg",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/setup.cfg?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/d429264c8c2f0f306a422900c2f41123e07c31b4",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/setup.cfg"
+ }
+ },
+ {
+ "name": "setup.py",
+ "path": "setup.py",
+ "sha": "88b4e0a1c8093fae2b4fa52534035f9f85ed0956",
+ "size": 2433,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/setup.py?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/setup.py",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/88b4e0a1c8093fae2b4fa52534035f9f85ed0956",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/setup.py",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/setup.py?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/88b4e0a1c8093fae2b4fa52534035f9f85ed0956",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/setup.py"
+ }
+ },
+ {
+ "name": "tests",
+ "path": "tests",
+ "sha": "88b4e0a1c8093fae2b4fa52534035f9f85ed0956",
+ "size": 0,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/tests?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/tests",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/88b4e0a1c8093fae2b4fa52534035f9f85ed0956",
+ "download_url": null,
+ "type": "dir",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/tests?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/trees/88b4e0a1c8093fae2b4fa52534035f9f85ed0956",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/tree/develop/tests"
+ }
+ },
+ {
+ "name": "todo.txt",
+ "path": "todo.txt",
+ "sha": "3e369beef1c9e64f0c10735d35aa8ad755daddc6",
+ "size": 1147,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/todo.txt?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/todo.txt",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/3e369beef1c9e64f0c10735d35aa8ad755daddc6",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/todo.txt",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/todo.txt?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/3e369beef1c9e64f0c10735d35aa8ad755daddc6",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/todo.txt"
+ }
+ },
+ {
+ "name": "update_definitions.sh",
+ "path": "update_definitions.sh",
+ "sha": "fbde266ea5ebd519b94d18f8f78ab825b02766df",
+ "size": 7877,
+ "url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/update_definitions.sh?ref=develop",
+ "html_url": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/update_definitions.sh",
+ "git_url": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/fbde266ea5ebd519b94d18f8f78ab825b02766df",
+ "download_url": "https://raw.githubusercontent.com/CityOfNewYork/NYCOpenRecords/develop/update_definitions.sh",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/contents/update_definitions.sh?ref=develop",
+ "git": "https://api.github.com/repos/CityOfNewYork/NYCOpenRecords/git/blobs/fbde266ea5ebd519b94d18f8f78ab825b02766df",
+ "html": "https://github.com/CityOfNewYork/NYCOpenRecords/blob/develop/update_definitions.sh"
+ }
+ }
+]
diff --git a/uv/spec/fixtures/github/contents_todo_txt.json b/uv/spec/fixtures/github/contents_todo_txt.json
new file mode 100644
index 00000000000..0870ce54613
--- /dev/null
+++ b/uv/spec/fixtures/github/contents_todo_txt.json
@@ -0,0 +1,18 @@
+{
+ "name": "todo.txt",
+ "path": "todo.txt",
+ "sha": "d040121111e637338dbfbb72f57b7cced03ae440",
+ "size": 924,
+ "url": "https://api.github.com/repos/gohugoio/hugo/contents/todo.txt?ref=master",
+ "html_url": "https://github.com/gohugoio/hugo/blob/master/todo.txt",
+ "git_url": "https://api.github.com/repos/gohugoio/hugo/git/blobs/d040121111e637338dbfbb72f57b7cced03ae440",
+ "download_url": "https://raw.githubusercontent.com/gohugoio/hugo/master/todo.txt",
+ "type": "file",
+ "content": "LSBXcml0ZSBjb2RlCi0gQ3V0IGEgcmVsZWFzZQotIEdlbmVyYWxseSBnb29k\nIHRoaW5ncwo=\n",
+ "encoding": "base64",
+ "_links": {
+ "self": "https://api.github.com/repos/gohugoio/hugo/contents/todo.txt?ref=master",
+ "git": "https://api.github.com/repos/gohugoio/hugo/git/blobs/d040121111e637338dbfbb72f57b7cced03ae440",
+ "html": "https://github.com/gohugoio/hugo/blob/master/todo.txt"
+ }
+}
diff --git a/uv/spec/fixtures/github/python_constraints_content.json b/uv/spec/fixtures/github/python_constraints_content.json
new file mode 100644
index 00000000000..95dc529c040
--- /dev/null
+++ b/uv/spec/fixtures/github/python_constraints_content.json
@@ -0,0 +1,18 @@
+{
+ "name": "constraints.txt",
+ "path": "constraints.txt",
+ "sha": "8d9a77a86256c11409622fd16d799d9718f1ff62",
+ "size": 29,
+ "url": "https://api.github.com/repos/gocardless/bump/contents/constraints.txt?ref=master",
+ "html_url": "https://github.com/gocardless/bump/blob/master/constraints.txt",
+ "git_url": "https://api.github.com/repos/gocardless/bump/git/blobs/8d9a77a86256c11409622fd16d799d9718f1ff62",
+ "download_url": "https://raw.githubusercontent.com/gocardless/bump/master/constraints.txt?token=ABMwe8vXxd4DBCEsxz3jMusk5sr_fFsoks5WJWE-wA%3D%3D",
+ "type": "file",
+ "content": "cmVxdWVzdHM8Mi4wLjAK\n",
+ "encoding": "base64",
+ "_links": {
+ "self": "https://api.github.com/repos/gocardless/bump/contents/constraints.txt?ref=master",
+ "git": "https://api.github.com/repos/gocardless/bump/git/blobs/8d9a77a86256c11409622fd16d799d9718f1ff62",
+ "html": "https://github.com/gocardless/bump/blob/master/constraints.txt"
+ }
+}
diff --git a/uv/spec/fixtures/github/requirements_content.json b/uv/spec/fixtures/github/requirements_content.json
new file mode 100644
index 00000000000..b00217ddfe6
--- /dev/null
+++ b/uv/spec/fixtures/github/requirements_content.json
@@ -0,0 +1,18 @@
+{
+ "name": "requirements.txt",
+ "path": "requirements.txt",
+ "sha": "8d9a77a86256c11409622fd16d799d9718f1ff62",
+ "size": 29,
+ "url": "https://api.github.com/repos/gocardless/bump/contents/requirements.txt?ref=master",
+ "html_url": "https://github.com/gocardless/bump/blob/master/requirements.txt",
+ "git_url": "https://api.github.com/repos/gocardless/bump/git/blobs/8d9a77a86256c11409622fd16d799d9718f1ff62",
+ "download_url": "https://raw.githubusercontent.com/gocardless/bump/master/requirements.txt?token=ABMwe8vXxd4DBCEsxz3jMusk5sr_fFsoks5WJWE-wA%3D%3D",
+ "type": "file",
+ "content": "cHN5Y29wZzI9PTIuNi4xCmx1aWdpPT0yLjIuMAo=",
+ "encoding": "base64",
+ "_links": {
+ "self": "https://api.github.com/repos/gocardless/bump/contents/requirements.txt?ref=master",
+ "git": "https://api.github.com/repos/gocardless/bump/git/blobs/8d9a77a86256c11409622fd16d799d9718f1ff62",
+ "html": "https://github.com/gocardless/bump/blob/master/requirements.txt"
+ }
+}
diff --git a/uv/spec/fixtures/github/requirements_in_content.json b/uv/spec/fixtures/github/requirements_in_content.json
new file mode 100644
index 00000000000..6459caba814
--- /dev/null
+++ b/uv/spec/fixtures/github/requirements_in_content.json
@@ -0,0 +1,18 @@
+{
+ "name": "requirements.in",
+ "path": "requirements.in",
+ "sha": "8d9a77a86256c11409622fd16d799d9718f1ff62",
+ "size": 29,
+ "url": "https://api.github.com/repos/gocardless/bump/contents/requirements.in?ref=master",
+ "html_url": "https://github.com/gocardless/bump/blob/master/requirements.in",
+ "git_url": "https://api.github.com/repos/gocardless/bump/git/blobs/8d9a77a86256c11409622fd16d799d9718f1ff62",
+ "download_url": "https://raw.githubusercontent.com/gocardless/bump/master/requirements.in?token=ABMwe8vXxd4DBCEsxz3jMusk5sr_fFsoks5WJWE-wA%3D%3D",
+ "type": "file",
+ "content": "cHN5Y29wZzI9PTIuNi4xCmx1aWdpPT0yLjIuMAo=",
+ "encoding": "base64",
+ "_links": {
+ "self": "https://api.github.com/repos/gocardless/bump/contents/requirements.in?ref=master",
+ "git": "https://api.github.com/repos/gocardless/bump/git/blobs/8d9a77a86256c11409622fd16d799d9718f1ff62",
+ "html": "https://github.com/gocardless/bump/blob/master/requirements.in"
+ }
+}
diff --git a/uv/spec/fixtures/github/requirements_with_cascade.json b/uv/spec/fixtures/github/requirements_with_cascade.json
new file mode 100644
index 00000000000..667afb15a5b
--- /dev/null
+++ b/uv/spec/fixtures/github/requirements_with_cascade.json
@@ -0,0 +1,18 @@
+{
+ "name": "requirements.txt",
+ "path": "requirements.txt",
+ "sha": "8d9a77a86256c11409622fd16d799d9718f1ff62",
+ "size": 29,
+ "url": "https://api.github.com/repos/gocardless/bump/contents/requirements.txt?ref=master",
+ "html_url": "https://github.com/gocardless/bump/blob/master/requirements.txt",
+ "git_url": "https://api.github.com/repos/gocardless/bump/git/blobs/8d9a77a86256c11409622fd16d799d9718f1ff62",
+ "download_url": "https://raw.githubusercontent.com/gocardless/bump/master/requirements.txt?token=ABMwe8vXxd4DBCEsxz3jMusk5sr_fFsoks5WJWE-wA%3D%3D",
+ "type": "file",
+ "content": "cmVxdWVzdHM9PTIuNC4xCi1yIC4vbW9yZV9yZXF1aXJlbWVudHMudHh0Ci1y\nIG5vX2RvdC9tb3JlX3JlcXVpcmVtZW50cy50eHQKLXIgY29tbWVudF9tb3Jl\nX3JlcXVpcmVtZW50cy50eHQgIyBUaGlzIGlzIGEgY29tbWVudAo=\n",
+ "encoding": "base64",
+ "_links": {
+ "self": "https://api.github.com/repos/gocardless/bump/contents/requirements.txt?ref=master",
+ "git": "https://api.github.com/repos/gocardless/bump/git/blobs/8d9a77a86256c11409622fd16d799d9718f1ff62",
+ "html": "https://github.com/gocardless/bump/blob/master/requirements.txt"
+ }
+}
diff --git a/uv/spec/fixtures/github/requirements_with_circular.json b/uv/spec/fixtures/github/requirements_with_circular.json
new file mode 100644
index 00000000000..2d5662d5b9c
--- /dev/null
+++ b/uv/spec/fixtures/github/requirements_with_circular.json
@@ -0,0 +1,18 @@
+{
+ "name": "requirements.txt",
+ "path": "requirements.txt",
+ "sha": "8d9a77a86256c11409622fd16d799d9718f1ff62",
+ "size": 29,
+ "url": "https://api.github.com/repos/gocardless/bump/contents/requirements.txt?ref=master",
+ "html_url": "https://github.com/gocardless/bump/blob/master/requirements.txt",
+ "git_url": "https://api.github.com/repos/gocardless/bump/git/blobs/8d9a77a86256c11409622fd16d799d9718f1ff62",
+ "download_url": "https://raw.githubusercontent.com/gocardless/bump/master/requirements.txt?token=ABMwe8vXxd4DBCEsxz3jMusk5sr_fFsoks5WJWE-wA%3D%3D",
+ "type": "file",
+ "content": "cmVxdWVzdHM9PTIuNC4xCi1yIC4vcmVxdWlyZW1lbnRzLnR4dAo=\n",
+ "encoding": "base64",
+ "_links": {
+ "self": "https://api.github.com/repos/gocardless/bump/contents/requirements.txt?ref=master",
+ "git": "https://api.github.com/repos/gocardless/bump/git/blobs/8d9a77a86256c11409622fd16d799d9718f1ff62",
+ "html": "https://github.com/gocardless/bump/blob/master/requirements.txt"
+ }
+}
diff --git a/uv/spec/fixtures/github/requirements_with_comments.json b/uv/spec/fixtures/github/requirements_with_comments.json
new file mode 100644
index 00000000000..7d865f6663a
--- /dev/null
+++ b/uv/spec/fixtures/github/requirements_with_comments.json
@@ -0,0 +1,18 @@
+{
+ "name": "requirements.txt",
+ "path": "requirements.txt",
+ "sha": "8d9a77a86256c11409622fd16d799d9718f1ff62",
+ "size": 29,
+ "url": "https://api.github.com/repos/gocardless/bump/contents/requirements.txt?ref=master",
+ "html_url": "https://github.com/gocardless/bump/blob/master/requirements.txt",
+ "git_url": "https://api.github.com/repos/gocardless/bump/git/blobs/8d9a77a86256c11409622fd16d799d9718f1ff62",
+ "download_url": "https://raw.githubusercontent.com/gocardless/bump/master/requirements.txt?token=ABMwe8vXxd4DBCEsxz3jMusk5sr_fFsoks5WJWE-wA%3D%3D",
+ "type": "file",
+ "content": "ICMgVGhpcyBpcyBhIGNvbW1lbnQKcHN5Y29wZzI9PTIuNi4xCmx1aWdpPT0y\nLjIuMAo=\n",
+ "encoding": "base64",
+ "_links": {
+ "self": "https://api.github.com/repos/gocardless/bump/contents/requirements.txt?ref=master",
+ "git": "https://api.github.com/repos/gocardless/bump/git/blobs/8d9a77a86256c11409622fd16d799d9718f1ff62",
+ "html": "https://github.com/gocardless/bump/blob/master/requirements.txt"
+ }
+}
diff --git a/uv/spec/fixtures/github/requirements_with_constraint.json b/uv/spec/fixtures/github/requirements_with_constraint.json
new file mode 100644
index 00000000000..522eafa9494
--- /dev/null
+++ b/uv/spec/fixtures/github/requirements_with_constraint.json
@@ -0,0 +1,18 @@
+{
+ "name": "requirements.txt",
+ "path": "requirements.txt",
+ "sha": "8d9a77a86256c11409622fd16d799d9718f1ff62",
+ "size": 29,
+ "url": "https://api.github.com/repos/gocardless/bump/contents/requirements.txt?ref=master",
+ "html_url": "https://github.com/gocardless/bump/blob/master/requirements.txt",
+ "git_url": "https://api.github.com/repos/gocardless/bump/git/blobs/8d9a77a86256c11409622fd16d799d9718f1ff62",
+ "download_url": "https://raw.githubusercontent.com/gocardless/bump/master/requirements.txt?token=ABMwe8vXxd4DBCEsxz3jMusk5sr_fFsoks5WJWE-wA%3D%3D",
+ "type": "file",
+ "content": "cmVxdWVzdHM9PTIuNC4xCi1jIC4vY29uc3RyYWludHMudHh0Cg==\n",
+ "encoding": "base64",
+ "_links": {
+ "self": "https://api.github.com/repos/gocardless/bump/contents/requirements.txt?ref=master",
+ "git": "https://api.github.com/repos/gocardless/bump/git/blobs/8d9a77a86256c11409622fd16d799d9718f1ff62",
+ "html": "https://github.com/gocardless/bump/blob/master/requirements.txt"
+ }
+}
diff --git a/uv/spec/fixtures/github/requirements_with_git_reference.json b/uv/spec/fixtures/github/requirements_with_git_reference.json
new file mode 100644
index 00000000000..6fa0b032cd3
--- /dev/null
+++ b/uv/spec/fixtures/github/requirements_with_git_reference.json
@@ -0,0 +1,18 @@
+{
+ "name": "requirements.txt",
+ "path": "requirements.txt",
+ "sha": "8d9a77a86256c11409622fd16d799d9718f1ff62",
+ "size": 29,
+ "url": "https://api.github.com/repos/gocardless/bump/contents/requirements.txt?ref=master",
+ "html_url": "https://github.com/gocardless/bump/blob/master/requirements.txt",
+ "git_url": "https://api.github.com/repos/gocardless/bump/git/blobs/8d9a77a86256c11409622fd16d799d9718f1ff62",
+ "download_url": "https://raw.githubusercontent.com/gocardless/bump/master/requirements.txt?token=ABMwe8vXxd4DBCEsxz3jMusk5sr_fFsoks5WJWE-wA%3D%3D",
+ "type": "file",
+ "content": "LWUgZ2l0K2h0dHBzOi8vZ2l0aHViLmNvbS9weXBhL3BpcGVudiNlZ2c9cGlw\nZW52CgpyZXF1ZXN0cwo=\n",
+ "encoding": "base64",
+ "_links": {
+ "self": "https://api.github.com/repos/gocardless/bump/contents/requirements.txt?ref=master",
+ "git": "https://api.github.com/repos/gocardless/bump/git/blobs/8d9a77a86256c11409622fd16d799d9718f1ff62",
+ "html": "https://github.com/gocardless/bump/blob/master/requirements.txt"
+ }
+}
diff --git a/uv/spec/fixtures/github/requirements_with_git_url_reference.json b/uv/spec/fixtures/github/requirements_with_git_url_reference.json
new file mode 100644
index 00000000000..38881ffd5db
--- /dev/null
+++ b/uv/spec/fixtures/github/requirements_with_git_url_reference.json
@@ -0,0 +1,18 @@
+{
+ "name": "requirements.txt",
+ "path": "requirements.txt",
+ "sha": "8d9a77a86256c11409622fd16d799d9718f1ff62",
+ "size": 29,
+ "url": "https://api.github.com/repos/gocardless/bump/contents/requirements.txt?ref=master",
+ "html_url": "https://github.com/gocardless/bump/blob/master/requirements.txt",
+ "git_url": "https://api.github.com/repos/gocardless/bump/git/blobs/8d9a77a86256c11409622fd16d799d9718f1ff62",
+ "download_url": "https://raw.githubusercontent.com/gocardless/bump/master/requirements.txt?token=ABMwe8vXxd4DBCEsxz3jMusk5sr_fFsoks5WJWE-wA%3D%3D",
+ "type": "file",
+ "content": "LWUgZ2l0K2dpdEBnaXRodWIuY29tOnB5cGEvcGlwZW52I2VnZz1waXBlbnYK\nCnJlcXVlc3RzCg==\n",
+ "encoding": "base64",
+ "_links": {
+ "self": "https://api.github.com/repos/gocardless/bump/contents/requirements.txt?ref=master",
+ "git": "https://api.github.com/repos/gocardless/bump/git/blobs/8d9a77a86256c11409622fd16d799d9718f1ff62",
+ "html": "https://github.com/gocardless/bump/blob/master/requirements.txt"
+ }
+}
diff --git a/uv/spec/fixtures/github/requirements_with_in_child.json b/uv/spec/fixtures/github/requirements_with_in_child.json
new file mode 100644
index 00000000000..f898728a500
--- /dev/null
+++ b/uv/spec/fixtures/github/requirements_with_in_child.json
@@ -0,0 +1,18 @@
+{
+ "name": "requirements.txt",
+ "path": "requirements.txt",
+ "sha": "8d9a77a86256c11409622fd16d799d9718f1ff62",
+ "size": 29,
+ "url": "https://api.github.com/repos/gocardless/bump/contents/requirements.txt?ref=master",
+ "html_url": "https://github.com/gocardless/bump/blob/master/requirements.txt",
+ "git_url": "https://api.github.com/repos/gocardless/bump/git/blobs/8d9a77a86256c11409622fd16d799d9718f1ff62",
+ "download_url": "https://raw.githubusercontent.com/gocardless/bump/master/requirements.txt?token=ABMwe8vXxd4DBCEsxz3jMusk5sr_fFsoks5WJWE-wA%3D%3D",
+ "type": "file",
+ "content": "cmVxdWVzdHM9PTIuNC4xCi1yIHNvbWUvbmVzdGVkL3JlcS5pbgo=\n",
+ "encoding": "base64",
+ "_links": {
+ "self": "https://api.github.com/repos/gocardless/bump/contents/requirements.txt?ref=master",
+ "git": "https://api.github.com/repos/gocardless/bump/git/blobs/8d9a77a86256c11409622fd16d799d9718f1ff62",
+ "html": "https://github.com/gocardless/bump/blob/master/requirements.txt"
+ }
+}
diff --git a/uv/spec/fixtures/github/requirements_with_no_binary.json b/uv/spec/fixtures/github/requirements_with_no_binary.json
new file mode 100644
index 00000000000..2fc4ef754d1
--- /dev/null
+++ b/uv/spec/fixtures/github/requirements_with_no_binary.json
@@ -0,0 +1,18 @@
+{
+ "name": "requirements.txt",
+ "path": "requirements.txt",
+ "sha": "8d9a77a86256c11409622fd16d799d9718f1ff62",
+ "size": 29,
+ "url": "https://api.github.com/repos/gocardless/bump/contents/requirements.txt?ref=master",
+ "html_url": "https://github.com/gocardless/bump/blob/master/requirements.txt",
+ "git_url": "https://api.github.com/repos/gocardless/bump/git/blobs/8d9a77a86256c11409622fd16d799d9718f1ff62",
+ "download_url": "https://raw.githubusercontent.com/gocardless/bump/master/requirements.txt?token=ABMwe8vXxd4DBCEsxz3jMusk5sr_fFsoks5WJWE-wA%3D%3D",
+ "type": "file",
+ "content": "IyBUaGlzIGlzIGEgY29tbWVudAotLW5vLWJpbmFyeSBwc3ljb3BnMgoKcHN5\nY29wZzI9PTIuNi4xCmx1aWdpPT0yLjIuMAo=\n",
+ "encoding": "base64",
+ "_links": {
+ "self": "https://api.github.com/repos/gocardless/bump/contents/requirements.txt?ref=master",
+ "git": "https://api.github.com/repos/gocardless/bump/git/blobs/8d9a77a86256c11409622fd16d799d9718f1ff62",
+ "html": "https://github.com/gocardless/bump/blob/master/requirements.txt"
+ }
+}
diff --git a/uv/spec/fixtures/github/requirements_with_path_dependencies.json b/uv/spec/fixtures/github/requirements_with_path_dependencies.json
new file mode 100644
index 00000000000..9747ef1805f
--- /dev/null
+++ b/uv/spec/fixtures/github/requirements_with_path_dependencies.json
@@ -0,0 +1,18 @@
+{
+ "name": "requirements.txt",
+ "path": "requirements.txt",
+ "sha": "8d9a77a86256c11409622fd16d799d9718f1ff62",
+ "size": 29,
+ "url": "https://api.github.com/repos/gocardless/bump/contents/requirements.txt?ref=master",
+ "html_url": "https://github.com/gocardless/bump/blob/master/requirements.txt",
+ "git_url": "https://api.github.com/repos/gocardless/bump/git/blobs/8d9a77a86256c11409622fd16d799d9718f1ff62",
+ "download_url": "https://raw.githubusercontent.com/gocardless/bump/master/requirements.txt?token=ABMwe8vXxd4DBCEsxz3jMusk5sr_fFsoks5WJWE-wA%3D%3D",
+ "type": "file",
+ "content": "LWUgLgotZSAiLi9teSIKLWUgJy4vbXktc2luZ2xlJwoKLi9teS1vdGhlcgouL3NvbWUvemlwLWZpbGUudGFyLmd6CgpmaWxlOi4KLWUgZmlsZTouCg==\n",
+ "encoding": "base64",
+ "_links": {
+ "self": "https://api.github.com/repos/gocardless/bump/contents/requirements.txt?ref=master",
+ "git": "https://api.github.com/repos/gocardless/bump/git/blobs/8d9a77a86256c11409622fd16d799d9718f1ff62",
+ "html": "https://github.com/gocardless/bump/blob/master/requirements.txt"
+ }
+}
diff --git a/uv/spec/fixtures/github/requirements_with_self_reference.json b/uv/spec/fixtures/github/requirements_with_self_reference.json
new file mode 100644
index 00000000000..84f4faeba7a
--- /dev/null
+++ b/uv/spec/fixtures/github/requirements_with_self_reference.json
@@ -0,0 +1,18 @@
+{
+ "name": "requirements.txt",
+ "path": "requirements.txt",
+ "sha": "8d9a77a86256c11409622fd16d799d9718f1ff62",
+ "size": 29,
+ "url": "https://api.github.com/repos/gocardless/bump/contents/requirements.txt?ref=master",
+ "html_url": "https://github.com/gocardless/bump/blob/master/requirements.txt",
+ "git_url": "https://api.github.com/repos/gocardless/bump/git/blobs/8d9a77a86256c11409622fd16d799d9718f1ff62",
+ "download_url": "https://raw.githubusercontent.com/gocardless/bump/master/requirements.txt?token=ABMwe8vXxd4DBCEsxz3jMusk5sr_fFsoks5WJWE-wA%3D%3D",
+ "type": "file",
+ "content": "LWUgLgo=\n",
+ "encoding": "base64",
+ "_links": {
+ "self": "https://api.github.com/repos/gocardless/bump/contents/requirements.txt?ref=master",
+ "git": "https://api.github.com/repos/gocardless/bump/git/blobs/8d9a77a86256c11409622fd16d799d9718f1ff62",
+ "html": "https://github.com/gocardless/bump/blob/master/requirements.txt"
+ }
+}
diff --git a/uv/spec/fixtures/github/requirements_with_self_reference_extras.json b/uv/spec/fixtures/github/requirements_with_self_reference_extras.json
new file mode 100644
index 00000000000..71da150ecda
--- /dev/null
+++ b/uv/spec/fixtures/github/requirements_with_self_reference_extras.json
@@ -0,0 +1,18 @@
+{
+ "name": "requirements.txt",
+ "path": "requirements.txt",
+ "sha": "8d9a77a86256c11409622fd16d799d9718f1ff62",
+ "size": 29,
+ "url": "https://api.github.com/repos/gocardless/bump/contents/requirements.txt?ref=master",
+ "html_url": "https://github.com/gocardless/bump/blob/master/requirements.txt",
+ "git_url": "https://api.github.com/repos/gocardless/bump/git/blobs/8d9a77a86256c11409622fd16d799d9718f1ff62",
+ "download_url": "https://raw.githubusercontent.com/gocardless/bump/master/requirements.txt?token=ABMwe8vXxd4DBCEsxz3jMusk5sr_fFsoks5WJWE-wA%3D%3D",
+ "type": "file",
+ "content": "LWUgLltkb2NzXQo=\n",
+ "encoding": "base64",
+ "_links": {
+ "self": "https://api.github.com/repos/gocardless/bump/contents/requirements.txt?ref=master",
+ "git": "https://api.github.com/repos/gocardless/bump/git/blobs/8d9a77a86256c11409622fd16d799d9718f1ff62",
+ "html": "https://github.com/gocardless/bump/blob/master/requirements.txt"
+ }
+}
diff --git a/uv/spec/fixtures/github/requirements_with_self_reference_not_editable.json b/uv/spec/fixtures/github/requirements_with_self_reference_not_editable.json
new file mode 100644
index 00000000000..62910aebba6
--- /dev/null
+++ b/uv/spec/fixtures/github/requirements_with_self_reference_not_editable.json
@@ -0,0 +1,18 @@
+{
+ "name": "requirements.txt",
+ "path": "requirements.txt",
+ "sha": "8d9a77a86256c11409622fd16d799d9718f1ff62",
+ "size": 29,
+ "url": "https://api.github.com/repos/gocardless/bump/contents/requirements.txt?ref=master",
+ "html_url": "https://github.com/gocardless/bump/blob/master/requirements.txt",
+ "git_url": "https://api.github.com/repos/gocardless/bump/git/blobs/8d9a77a86256c11409622fd16d799d9718f1ff62",
+ "download_url": "https://raw.githubusercontent.com/gocardless/bump/master/requirements.txt?token=ABMwe8vXxd4DBCEsxz3jMusk5sr_fFsoks5WJWE-wA%3D%3D",
+ "type": "file",
+ "content": "Lgo=\n",
+ "encoding": "base64",
+ "_links": {
+ "self": "https://api.github.com/repos/gocardless/bump/contents/requirements.txt?ref=master",
+ "git": "https://api.github.com/repos/gocardless/bump/git/blobs/8d9a77a86256c11409622fd16d799d9718f1ff62",
+ "html": "https://github.com/gocardless/bump/blob/master/requirements.txt"
+ }
+}
diff --git a/uv/spec/fixtures/github/requirements_with_simple_cascade.json b/uv/spec/fixtures/github/requirements_with_simple_cascade.json
new file mode 100644
index 00000000000..78bd8ab317a
--- /dev/null
+++ b/uv/spec/fixtures/github/requirements_with_simple_cascade.json
@@ -0,0 +1,18 @@
+{
+ "name": "requirements.txt",
+ "path": "requirements.txt",
+ "sha": "8d9a77a86256c11409622fd16d799d9718f1ff62",
+ "size": 29,
+ "url": "https://api.github.com/repos/gocardless/bump/contents/requirements.txt?ref=master",
+ "html_url": "https://github.com/gocardless/bump/blob/master/requirements.txt",
+ "git_url": "https://api.github.com/repos/gocardless/bump/git/blobs/8d9a77a86256c11409622fd16d799d9718f1ff62",
+ "download_url": "https://raw.githubusercontent.com/gocardless/bump/master/requirements.txt?token=ABMwe8vXxd4DBCEsxz3jMusk5sr_fFsoks5WJWE-wA%3D%3D",
+ "type": "file",
+ "content": "cmVxdWVzdHM9PTIuNC4xCi1yIGNhc2NhZGVkX3JlcXVpcmVtZW50cy50eHQK\n",
+ "encoding": "base64",
+ "_links": {
+ "self": "https://api.github.com/repos/gocardless/bump/contents/requirements.txt?ref=master",
+ "git": "https://api.github.com/repos/gocardless/bump/git/blobs/8d9a77a86256c11409622fd16d799d9718f1ff62",
+ "html": "https://github.com/gocardless/bump/blob/master/requirements.txt"
+ }
+}
diff --git a/uv/spec/fixtures/github/setup_cfg_content.json b/uv/spec/fixtures/github/setup_cfg_content.json
new file mode 100644
index 00000000000..16e45106e5e
--- /dev/null
+++ b/uv/spec/fixtures/github/setup_cfg_content.json
@@ -0,0 +1,18 @@
+{
+ "name": "setup.cfg",
+ "path": "setup.cfg",
+ "sha": "a99ba2c724c136387dc17eefcda2f9c003b5d705",
+ "size": 29,
+ "url": "https://api.github.com/repos/gocardless/bump/contents/setup.cfg?ref=master",
+ "html_url": "https://github.com/gocardless/bump/blob/master/setup.cfg",
+ "git_url": "https://api.github.com/repos/gocardless/bump/git/blobs/a99ba2c724c136387dc17eefcda2f9c003b5d705",
+ "download_url": "https://raw.githubusercontent.com/gocardless/bump/master/setup.cfg?token=ABMwe8vXxd4DBCEsxz3jMusk5sr_fFsoks5WJWE-wA%3D%3D",
+ "type": "file",
+ "content": "W21ldGFkYXRhXQpuYW1lID0gcHl0aG9uLXBhY2thZ2UKdmVyc2lvbiA9IDAuMApkZXNjcmlwdGlv\nbiA9IEV4YW1wbGUgc2V0dXAuY2ZnCnVybCA9IGh0dG9zOi8vZ2l0aHViLmNvbS9leGFtcGxlL3B5\ndGhvbi1wYWNrYWdlCmF1dGhvciA9IERlcGVuZGFib3QKCltvcHRpb25zXQpwYWNrYWdlcyA9IGZp\nbmQ6CnNldHVwX3JlcXVpcmVzID0KICAgIG51bXB5PT0xLjExLjAKICAgIHB5dGVzdC1ydW5uZXIK\naW5zdGFsbF9yZXF1aXJlcyA9CiAgICBib3RvMz09MS4zLjEKICAgIGZsYWtlOCA+IDIuNS40LCA8\nIDMuMC4wCiAgICBnb2NhcmRsZXNzX3BybwogICAgcGFuZGFzPT0wLjE5LjIKICAgIHBlcDg9PTEu\nNy4wCiAgICBwc3ljb3BnMj09Mi42LjEKICAgIHJhdmVuID09IDUuMzIuMAogICAgcmVxdWVzdHM9\nPTIuMTIuKgogICAgc2NpcHk9PTAuMTguMQogICAgc2Npa2l0LWxlYXJuPT0wLjE4LjEKCnRlc3Rz\nX3JlcXVpcmUgPQogICAgcHl0ZXN0PT0yLjkuMQogICAgcmVzcG9uc2VzPT0wLjUuMQoKW29wdGlv\nbnMuZXh0cmFzX3JlcXVpcmVdCkFQSSA9IGZsYXNrPT0wLjEyLjIK\n",
+ "encoding": "base64",
+ "_links": {
+ "self": "https://api.github.com/repos/gocardless/bump/contents/setup.cfg?ref=master",
+ "git": "https://api.github.com/repos/gocardless/bump/git/blobs/a99ba2c724c136387dc17eefcda2f9c003b5d705",
+ "html": "https://github.com/gocardless/bump/blob/master/setup.cfg"
+ }
+}
diff --git a/uv/spec/fixtures/github/setup_content.json b/uv/spec/fixtures/github/setup_content.json
new file mode 100644
index 00000000000..ed0936ad112
--- /dev/null
+++ b/uv/spec/fixtures/github/setup_content.json
@@ -0,0 +1,18 @@
+{
+ "name": "setup.py",
+ "path": "setup.py",
+ "sha": "8d9a77a86256c11409622fd16d799d9718f1ff62",
+ "size": 29,
+ "url": "https://api.github.com/repos/gocardless/bump/contents/setup.py?ref=master",
+ "html_url": "https://github.com/gocardless/bump/blob/master/setup.py",
+ "git_url": "https://api.github.com/repos/gocardless/bump/git/blobs/8d9a77a86256c11409622fd16d799d9718f1ff62",
+ "download_url": "https://raw.githubusercontent.com/gocardless/bump/master/setup.py?token=ABMwe8vXxd4DBCEsxz3jMusk5sr_fFsoks5WJWE-wA%3D%3D",
+ "type": "file",
+ "content": "ZnJvbSBzZXR1cHRvb2xzIGltcG9ydCBzZXR1cCwgZmluZF9wYWNrYWdlcwoK\nc2V0dXAobmFtZT0ncHl0aG9uLXBhY2thZ2UnLAogICAgICB2ZXJzaW9uPScw\nLjAnLAogICAgICBkZXNjcmlwdGlvbj0nRXhhbXBsZSBzZXR1cC5weScsCiAg\nICAgIHVybD0naHR0b3M6Ly9naXRodWIuY29tL2V4YW1wbGUvcHl0aG9uLXBh\nY2thZ2UnLAogICAgICBhdXRob3I9J0RlcGVuZGFib3QnLAogICAgICBzY3Jp\ncHRzPVtdLAogICAgICBwYWNrYWdlcz1maW5kX3BhY2thZ2VzKCksCiAgICAg\nIHNldHVwX3JlcXVpcmVzPVsKICAgICAgICAgICdudW1weT09MS4xMS4wJywK\nICAgICAgICAgICdweXRlc3QtcnVubmVyJywKICAgICAgXSwKICAgICAgaW5z\ndGFsbF9yZXF1aXJlcz1bCiAgICAgICAgICAnYm90bzM9PTEuMy4xJywKICAg\nICAgICAgICdmbGFrZTg9PTIuNS40JywKICAgICAgICAgICdnb2NhcmRsZXNz\nX3Bybz09MC4yLjMnLAogICAgICAgICAgJ251bXB5PT0xLjExLjAnLAogICAg\nICAgICAgJ3BhbmRhcz09MC4xOS4yJywKICAgICAgICAgICdwZXA4PT0xLjcu\nMCcsCiAgICAgICAgICAncHN5Y29wZzI9PTIuNi4xJywKICAgICAgICAgICdy\nYXZlbj09NS4zMi4wJywKICAgICAgICAgICdyZXF1ZXN0cz09Mi4xMi40JywK\nICAgICAgICAgICdzY2lweT09MC4xOC4xJywKICAgICAgICAgICdzY2lraXQt\nbGVhcm49PTAuMTguMScsCiAgICAgIF0sCiAgICAgIHRlc3RzX3JlcXVpcmU9\nWwogICAgICAgICAgJ3B5dGVzdD09Mi45LjEnLAogICAgICAgICAgJ3Jlc3Bv\nbnNlcz09MC41LjEnLAogICAgICBdCiAgICAgICkK\n",
+ "encoding": "base64",
+ "_links": {
+ "self": "https://api.github.com/repos/gocardless/bump/contents/setup.py?ref=master",
+ "git": "https://api.github.com/repos/gocardless/bump/git/blobs/8d9a77a86256c11409622fd16d799d9718f1ff62",
+ "html": "https://github.com/gocardless/bump/blob/master/setup.py"
+ }
+}
diff --git a/uv/spec/fixtures/path_dependencies/taxtea-0.6.0.tar.gz b/uv/spec/fixtures/path_dependencies/taxtea-0.6.0.tar.gz
new file mode 100644
index 00000000000..6f7c3d42606
Binary files /dev/null and b/uv/spec/fixtures/path_dependencies/taxtea-0.6.0.tar.gz differ
diff --git a/uv/spec/fixtures/pip_compile_files/bounded.in b/uv/spec/fixtures/pip_compile_files/bounded.in
new file mode 100644
index 00000000000..8483ba8555f
--- /dev/null
+++ b/uv/spec/fixtures/pip_compile_files/bounded.in
@@ -0,0 +1,5 @@
+flaky
+pytest
+pytest-xdist
+mock
+Attrs<=17.4.0
diff --git a/uv/spec/fixtures/pip_compile_files/celery_extra_sqs.in b/uv/spec/fixtures/pip_compile_files/celery_extra_sqs.in
new file mode 100644
index 00000000000..29a9f6c6b16
--- /dev/null
+++ b/uv/spec/fixtures/pip_compile_files/celery_extra_sqs.in
@@ -0,0 +1 @@
+celery[sqs]
diff --git a/uv/spec/fixtures/pip_compile_files/editable.in b/uv/spec/fixtures/pip_compile_files/editable.in
new file mode 100644
index 00000000000..e7d4994ccf6
--- /dev/null
+++ b/uv/spec/fixtures/pip_compile_files/editable.in
@@ -0,0 +1,4 @@
+-e git+https://github.com/box/flaky.git@v3.5.3#egg=flaky
+-e git+https://github.com/testing-cabal/mock.git@2.0.0#egg=mock
+
+Attrs
diff --git a/uv/spec/fixtures/pip_compile_files/extra.in b/uv/spec/fixtures/pip_compile_files/extra.in
new file mode 100644
index 00000000000..78bef69cbe9
--- /dev/null
+++ b/uv/spec/fixtures/pip_compile_files/extra.in
@@ -0,0 +1,2 @@
+flask
+sentry-sdk[flask]
diff --git a/uv/spec/fixtures/pip_compile_files/extra_hashes.in b/uv/spec/fixtures/pip_compile_files/extra_hashes.in
new file mode 100644
index 00000000000..181b5c77b01
--- /dev/null
+++ b/uv/spec/fixtures/pip_compile_files/extra_hashes.in
@@ -0,0 +1,2 @@
+pytest
+pyasn1-modules
diff --git a/uv/spec/fixtures/pip_compile_files/git_source_bad_ref.in b/uv/spec/fixtures/pip_compile_files/git_source_bad_ref.in
new file mode 100644
index 00000000000..cb185f14f88
--- /dev/null
+++ b/uv/spec/fixtures/pip_compile_files/git_source_bad_ref.in
@@ -0,0 +1,6 @@
+flaky
+pytest
+pytest-xdist
+mock
+Attrs
+-e git+https://github.com/sarugaku/pythonfinder.git@v15.1.2#egg=pythonfinder
diff --git a/uv/spec/fixtures/pip_compile_files/git_source_unreachable.in b/uv/spec/fixtures/pip_compile_files/git_source_unreachable.in
new file mode 100644
index 00000000000..2114334d11f
--- /dev/null
+++ b/uv/spec/fixtures/pip_compile_files/git_source_unreachable.in
@@ -0,0 +1,6 @@
+flaky
+pytest
+pytest-xdist
+mock
+Attrs
+-e git+https://github.com/greysteil/unreachable#egg=unreachable
diff --git a/uv/spec/fixtures/pip_compile_files/imports_dev.in b/uv/spec/fixtures/pip_compile_files/imports_dev.in
new file mode 100644
index 00000000000..429c53dda42
--- /dev/null
+++ b/uv/spec/fixtures/pip_compile_files/imports_dev.in
@@ -0,0 +1 @@
+-r dev.txt
diff --git a/uv/spec/fixtures/pip_compile_files/imports_mirror.in b/uv/spec/fixtures/pip_compile_files/imports_mirror.in
new file mode 100644
index 00000000000..20ab5ce8b10
--- /dev/null
+++ b/uv/spec/fixtures/pip_compile_files/imports_mirror.in
@@ -0,0 +1 @@
+-r mirror.txt
diff --git a/uv/spec/fixtures/pip_compile_files/imports_setup.in b/uv/spec/fixtures/pip_compile_files/imports_setup.in
new file mode 100644
index 00000000000..a4fa73918fb
--- /dev/null
+++ b/uv/spec/fixtures/pip_compile_files/imports_setup.in
@@ -0,0 +1,7 @@
+-e .
+
+flaky
+pytest
+pytest-xdist
+mock
+Attrs
diff --git a/uv/spec/fixtures/pip_compile_files/imports_shared.in b/uv/spec/fixtures/pip_compile_files/imports_shared.in
new file mode 100644
index 00000000000..29a2aa807b5
--- /dev/null
+++ b/uv/spec/fixtures/pip_compile_files/imports_shared.in
@@ -0,0 +1,3 @@
+-r shared.in
+
+moto==1.3.3
diff --git a/uv/spec/fixtures/pip_compile_files/incompatible_versions.in b/uv/spec/fixtures/pip_compile_files/incompatible_versions.in
new file mode 100644
index 00000000000..d88e5ef2ba9
--- /dev/null
+++ b/uv/spec/fixtures/pip_compile_files/incompatible_versions.in
@@ -0,0 +1,3 @@
+ansible
+jinja2-cli[yaml]
+awscli
diff --git a/uv/spec/fixtures/pip_compile_files/met_marker.in b/uv/spec/fixtures/pip_compile_files/met_marker.in
new file mode 100644
index 00000000000..30ef8567544
--- /dev/null
+++ b/uv/spec/fixtures/pip_compile_files/met_marker.in
@@ -0,0 +1,5 @@
+flaky; python_version < '2.8'
+pytest
+pytest-xdist
+mock
+Attrs
diff --git a/uv/spec/fixtures/pip_compile_files/native_dependencies.in b/uv/spec/fixtures/pip_compile_files/native_dependencies.in
new file mode 100644
index 00000000000..e3486b78b1d
--- /dev/null
+++ b/uv/spec/fixtures/pip_compile_files/native_dependencies.in
@@ -0,0 +1,3 @@
+numpy
+cryptography
+pandas
diff --git a/uv/spec/fixtures/pip_compile_files/no_binary.in b/uv/spec/fixtures/pip_compile_files/no_binary.in
new file mode 100644
index 00000000000..09cc8bc4589
--- /dev/null
+++ b/uv/spec/fixtures/pip_compile_files/no_binary.in
@@ -0,0 +1 @@
+psycopg2 --no-binary psycopg2
diff --git a/uv/spec/fixtures/pip_compile_files/no_binary_uv.in b/uv/spec/fixtures/pip_compile_files/no_binary_uv.in
new file mode 100644
index 00000000000..08018c1cdc3
--- /dev/null
+++ b/uv/spec/fixtures/pip_compile_files/no_binary_uv.in
@@ -0,0 +1,2 @@
+psycopg2
+--no-binary psycopg2
diff --git a/uv/spec/fixtures/pip_compile_files/python_dateutil.in b/uv/spec/fixtures/pip_compile_files/python_dateutil.in
new file mode 100644
index 00000000000..668f62e4ba0
--- /dev/null
+++ b/uv/spec/fixtures/pip_compile_files/python_dateutil.in
@@ -0,0 +1 @@
+python-dateutil==2.6.0
diff --git a/uv/spec/fixtures/pip_compile_files/python_header.in b/uv/spec/fixtures/pip_compile_files/python_header.in
new file mode 100644
index 00000000000..29a9f6c6b16
--- /dev/null
+++ b/uv/spec/fixtures/pip_compile_files/python_header.in
@@ -0,0 +1 @@
+celery[sqs]
diff --git a/uv/spec/fixtures/pip_compile_files/requests.in b/uv/spec/fixtures/pip_compile_files/requests.in
new file mode 100644
index 00000000000..f2293605cf1
--- /dev/null
+++ b/uv/spec/fixtures/pip_compile_files/requests.in
@@ -0,0 +1 @@
+requests
diff --git a/uv/spec/fixtures/pip_compile_files/resolves_differently_by_python.in b/uv/spec/fixtures/pip_compile_files/resolves_differently_by_python.in
new file mode 100644
index 00000000000..7fd2f70508e
--- /dev/null
+++ b/uv/spec/fixtures/pip_compile_files/resolves_differently_by_python.in
@@ -0,0 +1 @@
+tornado==5.1.0
diff --git a/uv/spec/fixtures/pip_compile_files/setuptools.in b/uv/spec/fixtures/pip_compile_files/setuptools.in
new file mode 100644
index 00000000000..49fe098d9e6
--- /dev/null
+++ b/uv/spec/fixtures/pip_compile_files/setuptools.in
@@ -0,0 +1 @@
+setuptools
diff --git a/uv/spec/fixtures/pip_compile_files/strip_extras.in b/uv/spec/fixtures/pip_compile_files/strip_extras.in
new file mode 100644
index 00000000000..b1db984ed70
--- /dev/null
+++ b/uv/spec/fixtures/pip_compile_files/strip_extras.in
@@ -0,0 +1 @@
+cachecontrol[filecache]
diff --git a/uv/spec/fixtures/pip_compile_files/superstring.in b/uv/spec/fixtures/pip_compile_files/superstring.in
new file mode 100644
index 00000000000..e82b9fbabe5
--- /dev/null
+++ b/uv/spec/fixtures/pip_compile_files/superstring.in
@@ -0,0 +1,3 @@
+Flask-SQLAlchemy
+SQLAlchemy
+zope.SQLAlchemy
diff --git a/uv/spec/fixtures/pip_compile_files/unmet_marker.in b/uv/spec/fixtures/pip_compile_files/unmet_marker.in
new file mode 100644
index 00000000000..029003a8e69
--- /dev/null
+++ b/uv/spec/fixtures/pip_compile_files/unmet_marker.in
@@ -0,0 +1,5 @@
+flaky; python_version < '3.4'
+pytest
+pytest-xdist
+mock
+Attrs
diff --git a/uv/spec/fixtures/pip_compile_files/unpinned.in b/uv/spec/fixtures/pip_compile_files/unpinned.in
new file mode 100644
index 00000000000..9e636b9fc7b
--- /dev/null
+++ b/uv/spec/fixtures/pip_compile_files/unpinned.in
@@ -0,0 +1,5 @@
+flaky
+pytest
+pytest-xdist
+mock
+Attrs
diff --git a/uv/spec/fixtures/pip_compile_files/unresolvable.in b/uv/spec/fixtures/pip_compile_files/unresolvable.in
new file mode 100644
index 00000000000..9d36d476e1d
--- /dev/null
+++ b/uv/spec/fixtures/pip_compile_files/unresolvable.in
@@ -0,0 +1,4 @@
+boto3==1.9.27
+botocore==1.10.84
+moto==1.3.6
+attrs<=17.4.0
diff --git a/uv/spec/fixtures/pip_compile_files/unsafe.in b/uv/spec/fixtures/pip_compile_files/unsafe.in
new file mode 100644
index 00000000000..39304807fbc
--- /dev/null
+++ b/uv/spec/fixtures/pip_compile_files/unsafe.in
@@ -0,0 +1 @@
+flake8
diff --git a/uv/spec/fixtures/pip_compile_files/vcs_url.in b/uv/spec/fixtures/pip_compile_files/vcs_url.in
new file mode 100644
index 00000000000..cf1ae99c61f
--- /dev/null
+++ b/uv/spec/fixtures/pip_compile_files/vcs_url.in
@@ -0,0 +1,2 @@
+git+https://github.com/testing-cabal/mock.git@2.0.0
+Attrs
diff --git a/uv/spec/fixtures/pip_conf_files/custom_index b/uv/spec/fixtures/pip_conf_files/custom_index
new file mode 100644
index 00000000000..30fdb6a1f39
--- /dev/null
+++ b/uv/spec/fixtures/pip_conf_files/custom_index
@@ -0,0 +1,2 @@
+[global]
+index-url = https://pypi.weasyldev.com/weasyl/source/+simple
diff --git a/uv/spec/fixtures/pip_conf_files/custom_index_double_at b/uv/spec/fixtures/pip_conf_files/custom_index_double_at
new file mode 100644
index 00000000000..d1c48e029fd
--- /dev/null
+++ b/uv/spec/fixtures/pip_conf_files/custom_index_double_at
@@ -0,0 +1,2 @@
+[global]
+index-url = https://me@mydomain.com:password@pypi.weasyldev.com/weasyl/source/+simple
diff --git a/uv/spec/fixtures/pip_conf_files/extra_index b/uv/spec/fixtures/pip_conf_files/extra_index
new file mode 100644
index 00000000000..1dbb9c39f0e
--- /dev/null
+++ b/uv/spec/fixtures/pip_conf_files/extra_index
@@ -0,0 +1,2 @@
+[global]
+extra-index-url = https://pypi.weasyldev.com/weasyl/source/+simple
diff --git a/uv/spec/fixtures/pip_conf_files/extra_index_env_variable b/uv/spec/fixtures/pip_conf_files/extra_index_env_variable
new file mode 100644
index 00000000000..cc4a476a24f
--- /dev/null
+++ b/uv/spec/fixtures/pip_conf_files/extra_index_env_variable
@@ -0,0 +1,2 @@
+[global]
+extra-index-url = https://pypi.weasyldev.com/${SECURE_NAME}/source/+simple
diff --git a/uv/spec/fixtures/pip_conf_files/extra_index_env_variable_basic_auth b/uv/spec/fixtures/pip_conf_files/extra_index_env_variable_basic_auth
new file mode 100644
index 00000000000..dfcbbfe7e84
--- /dev/null
+++ b/uv/spec/fixtures/pip_conf_files/extra_index_env_variable_basic_auth
@@ -0,0 +1,2 @@
+[global]
+extra-index-url = https://${CREDENTIALS}@pypi.weasyldev.com/source/+simple/
diff --git a/uv/spec/fixtures/pipfile_files/arbitrary_equality b/uv/spec/fixtures/pipfile_files/arbitrary_equality
new file mode 100644
index 00000000000..684fe70d565
--- /dev/null
+++ b/uv/spec/fixtures/pipfile_files/arbitrary_equality
@@ -0,0 +1,10 @@
+[[source]]
+name = "pypi"
+url = "https://pypi.org/simple"
+verify_ssl = true
+
+[dev-packages]
+pytest = "===3.4.0"
+
+[packages]
+requests = "===2.18.0"
diff --git a/uv/spec/fixtures/pipfile_files/arbitrary_equality.lock b/uv/spec/fixtures/pipfile_files/arbitrary_equality.lock
new file mode 100644
index 00000000000..574c85581dc
--- /dev/null
+++ b/uv/spec/fixtures/pipfile_files/arbitrary_equality.lock
@@ -0,0 +1,100 @@
+{
+ "_meta": {
+ "hash": {
+ "sha256": "d47662ae090ae8b438f77c7ed9b3d9c622cc62a65486c89aa9bc86a22f49fbb9"
+ },
+ "pipfile-spec": 6,
+ "requires": {},
+ "sources": [
+ {
+ "url": "https://pypi.org/simple",
+ "verify_ssl": true
+ }
+ ]
+ },
+ "default": {
+ "certifi": {
+ "hashes": [
+ "sha256:13e698f54293db9f89122b0581843a782ad0934a4fe0172d2a980ba77fc61bb7",
+ "sha256:9fa520c1bacfb634fa7af20a76bcbd3d5fb390481724c597da32c719a7dca4b0"
+ ],
+ "version": "==2018.4.16"
+ },
+ "chardet": {
+ "hashes": [
+ "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae",
+ "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"
+ ],
+ "version": "==3.0.4"
+ },
+ "idna": {
+ "hashes": [
+ "sha256:3cb5ce08046c4e3a560fc02f138d0ac63e00f8ce5901a56b32ec8b7994082aab",
+ "sha256:cc19709fd6d0cbfed39ea875d29ba6d4e22c0cebc510a76d6302a28385e8bb70"
+ ],
+ "version": "==2.5"
+ },
+ "requests": {
+ "hashes": [
+ "sha256:5e88d64aa56ac0fda54e77fb9762ebc65879e171b746d5479a33c4082519d6c6",
+ "sha256:cd0189f962787284bff715fddaad478eb4d9c15aa167bd64e52ea0f661e7ea5c"
+ ],
+ "index": "pypi",
+ "version": "===2.18.0"
+ },
+ "urllib3": {
+ "hashes": [
+ "sha256:8ed6d5c1ff9d6ba84677310060d6a3a78ca3072ce0684cb3c645023009c114b1",
+ "sha256:b14486978518ca0901a76ba973d7821047409d7f726f22156b24e83fd71382a5"
+ ],
+ "version": "==1.21.1"
+ }
+ },
+ "develop": {
+ "attrs": {
+ "hashes": [
+ "sha256:4b90b09eeeb9b88c35bc642cbac057e45a5fd85367b985bd2809c62b7b939265",
+ "sha256:e0d0eb91441a3b53dab4d9b743eafc1ac44476296a2053b6ca3af0b139faf87b"
+ ],
+ "version": "==18.1.0"
+ },
+ "funcsigs": {
+ "hashes": [
+ "sha256:330cc27ccbf7f1e992e69fef78261dc7c6569012cf397db8d3de0234e6c937ca",
+ "sha256:a7bb0f2cf3a3fd1ab2732cb49eba4252c2af4240442415b4abce3b87022a8f50"
+ ],
+ "markers": "python_version < '3.0'",
+ "version": "==1.0.2"
+ },
+ "pluggy": {
+ "hashes": [
+ "sha256:7f8ae7f5bdf75671a718d2daf0a64b7885f74510bcd98b1a0bb420eb9a9d0cff",
+ "sha256:d345c8fe681115900d6da8d048ba67c25df42973bda370783cd58826442dcd7c",
+ "sha256:e160a7fcf25762bb60efc7e171d4497ff1d8d2d75a3d0df7a21b76821ecbf5c5"
+ ],
+ "version": "==0.6.0"
+ },
+ "py": {
+ "hashes": [
+ "sha256:29c9fab495d7528e80ba1e343b958684f4ace687327e6f789a94bf3d1915f881",
+ "sha256:983f77f3331356039fdd792e9220b7b8ee1aa6bd2b25f567a963ff1de5a64f6a"
+ ],
+ "version": "==1.5.3"
+ },
+ "pytest": {
+ "hashes": [
+ "sha256:6074ea3b9c999bd6d0df5fa9d12dd95ccd23550df2a582f5f5b848331d2e82ca",
+ "sha256:95fa025cd6deb5d937e04e368a00552332b58cae23f63b76c8c540ff1733ab6d"
+ ],
+ "index": "pypi",
+ "version": "===3.4.0"
+ },
+ "six": {
+ "hashes": [
+ "sha256:70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9",
+ "sha256:832dc0e10feb1aa2c68dcc57dbb658f1c7e65b9b61af69048abc87a2db00a0eb"
+ ],
+ "version": "==1.11.0"
+ }
+ }
+}
diff --git a/uv/spec/fixtures/pipfile_files/conflict_at_current b/uv/spec/fixtures/pipfile_files/conflict_at_current
new file mode 100644
index 00000000000..8a19ad69169
--- /dev/null
+++ b/uv/spec/fixtures/pipfile_files/conflict_at_current
@@ -0,0 +1,11 @@
+[[source]]
+name = "pypi"
+url = "https://pypi.org/simple"
+verify_ssl = true
+
+[dev-packages]
+pytest = "==3.4.0"
+
+[packages]
+requests = "==2.18.0"
+chardet = "==3.0.0"
diff --git a/uv/spec/fixtures/pipfile_files/conflict_at_current.lock b/uv/spec/fixtures/pipfile_files/conflict_at_current.lock
new file mode 100644
index 00000000000..9f4984d686f
--- /dev/null
+++ b/uv/spec/fixtures/pipfile_files/conflict_at_current.lock
@@ -0,0 +1,67 @@
+{
+ "_meta": {
+ "hash": {
+ "sha256": "e2a3f489b7a8297b152f4d4133fff8b23650c3cfe2dd4d0d70ca20d8af8230c3"
+ },
+ "pipfile-spec": 6,
+ "requires": {},
+ "sources": [
+ {
+ "url": "https://pypi.org/simple",
+ "verify_ssl": true
+ }
+ ]
+ },
+ "default": {
+ "chardet": {
+ "hashes": [
+ "sha256:171dfc754d56c16b82cf77ac3eee1d42db9bc2f26c2c61c6573426d2a108d9e3",
+ "sha256:bedd581d3daea4180b3cb555940dcbc89916e7922b070d2a9a37e660791e90a2"
+ ],
+ "version": "==3.0.0"
+ },
+ "requests": {
+ "hashes": [
+ "sha256:5e88d64aa56ac0fda54e77fb9762ebc65879e171b746d5479a33c4082519d6c6",
+ "sha256:cd0189f962787284bff715fddaad478eb4d9c15aa167bd64e52ea0f661e7ea5c"
+ ],
+ "version": "==2.18.0"
+ }
+ },
+ "develop": {
+ "attrs": {
+ "hashes": [
+ "sha256:1c7960ccfd6a005cd9f7ba884e6316b5e430a3f1a6c37c5f87d8b43f83b54ec9",
+ "sha256:a17a9573a6f475c99b551c0e0a812707ddda1ec9653bed04c13841404ed6f450"
+ ],
+ "version": "==17.4.0"
+ },
+ "pluggy": {
+ "hashes": [
+ "sha256:7f8ae7f5bdf75671a718d2daf0a64b7885f74510bcd98b1a0bb420eb9a9d0cff"
+ ],
+ "version": "==0.6.0"
+ },
+ "py": {
+ "hashes": [
+ "sha256:29c9fab495d7528e80ba1e343b958684f4ace687327e6f789a94bf3d1915f881",
+ "sha256:983f77f3331356039fdd792e9220b7b8ee1aa6bd2b25f567a963ff1de5a64f6a"
+ ],
+ "version": "==1.5.3"
+ },
+ "pytest": {
+ "hashes": [
+ "sha256:6074ea3b9c999bd6d0df5fa9d12dd95ccd23550df2a582f5f5b848331d2e82ca",
+ "sha256:95fa025cd6deb5d937e04e368a00552332b58cae23f63b76c8c540ff1733ab6d"
+ ],
+ "version": "==3.4.0"
+ },
+ "six": {
+ "hashes": [
+ "sha256:70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9",
+ "sha256:832dc0e10feb1aa2c68dcc57dbb658f1c7e65b9b61af69048abc87a2db00a0eb"
+ ],
+ "version": "==1.11.0"
+ }
+ }
+}
diff --git a/uv/spec/fixtures/pipfile_files/conflict_at_latest b/uv/spec/fixtures/pipfile_files/conflict_at_latest
new file mode 100644
index 00000000000..be6abd85be3
--- /dev/null
+++ b/uv/spec/fixtures/pipfile_files/conflict_at_latest
@@ -0,0 +1,11 @@
+[[source]]
+name = "pypi"
+url = "https://pypi.org/simple"
+verify_ssl = true
+
+[dev-packages]
+pytest = "==3.4.0"
+
+[packages]
+requests = "==2.6.0"
+chardet = "==3.0.0"
diff --git a/uv/spec/fixtures/pipfile_files/conflict_at_latest.lock b/uv/spec/fixtures/pipfile_files/conflict_at_latest.lock
new file mode 100644
index 00000000000..50c3d931c4c
--- /dev/null
+++ b/uv/spec/fixtures/pipfile_files/conflict_at_latest.lock
@@ -0,0 +1,67 @@
+{
+ "_meta": {
+ "hash": {
+ "sha256": "e2a3f489b7a8297b152f4d4133fff8b23650c3cfe2dd4d0d70ca20d8af8230c3"
+ },
+ "pipfile-spec": 6,
+ "requires": {},
+ "sources": [
+ {
+ "url": "https://pypi.org/simple",
+ "verify_ssl": true
+ }
+ ]
+ },
+ "default": {
+ "chardet": {
+ "hashes": [
+ "sha256:171dfc754d56c16b82cf77ac3eee1d42db9bc2f26c2c61c6573426d2a108d9e3",
+ "sha256:bedd581d3daea4180b3cb555940dcbc89916e7922b070d2a9a37e660791e90a2"
+ ],
+ "version": "==3.0.0"
+ },
+ "requests": {
+ "hashes": [
+ "sha256:1cdbed1f0e236f35ef54e919982c7a338e4fea3786310933d3a7887a04b74d75",
+ "sha256:fdb9af60d47ca57a80df0a213336019a34ff6192d8fff361c349f2c8398fe460"
+ ],
+ "version": "==2.6.0"
+ }
+ },
+ "develop": {
+ "attrs": {
+ "hashes": [
+ "sha256:1c7960ccfd6a005cd9f7ba884e6316b5e430a3f1a6c37c5f87d8b43f83b54ec9",
+ "sha256:a17a9573a6f475c99b551c0e0a812707ddda1ec9653bed04c13841404ed6f450"
+ ],
+ "version": "==17.4.0"
+ },
+ "pluggy": {
+ "hashes": [
+ "sha256:7f8ae7f5bdf75671a718d2daf0a64b7885f74510bcd98b1a0bb420eb9a9d0cff"
+ ],
+ "version": "==0.6.0"
+ },
+ "py": {
+ "hashes": [
+ "sha256:29c9fab495d7528e80ba1e343b958684f4ace687327e6f789a94bf3d1915f881",
+ "sha256:983f77f3331356039fdd792e9220b7b8ee1aa6bd2b25f567a963ff1de5a64f6a"
+ ],
+ "version": "==1.5.3"
+ },
+ "pytest": {
+ "hashes": [
+ "sha256:6074ea3b9c999bd6d0df5fa9d12dd95ccd23550df2a582f5f5b848331d2e82ca",
+ "sha256:95fa025cd6deb5d937e04e368a00552332b58cae23f63b76c8c540ff1733ab6d"
+ ],
+ "version": "==3.4.0"
+ },
+ "six": {
+ "hashes": [
+ "sha256:70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9",
+ "sha256:832dc0e10feb1aa2c68dcc57dbb658f1c7e65b9b61af69048abc87a2db00a0eb"
+ ],
+ "version": "==1.11.0"
+ }
+ }
+}
diff --git a/uv/spec/fixtures/pipfile_files/edited.lock b/uv/spec/fixtures/pipfile_files/edited.lock
new file mode 100644
index 00000000000..098f74c5392
--- /dev/null
+++ b/uv/spec/fixtures/pipfile_files/edited.lock
@@ -0,0 +1,56 @@
+{
+ "_meta": {
+ "hash": {
+ "sha256": "c402ea48092e9d467af51a483bb8dd8ad0620e11c94f009dcd433f97a99d45db"
+ },
+ "pipfile-spec": 6,
+ "requires": {},
+ "sources": [
+ {
+ "url": "https://pypi.org/simple",
+ "verify_ssl": true
+ }
+ ]
+ },
+ "default": {
+ "certifi": {
+ "hashes": [
+ "sha256:244be0d93b71e93fc0a0a479862051414d0e00e16435707e5bf5000f92e04694",
+ "sha256:5ec74291ca1136b40f0379e1128ff80e866597e4e2c1e755739a913bbc3613c0"
+ ],
+ "version": "==2017.11.5"
+ },
+ "chardet": {
+ "hashes": [
+ "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691",
+ "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae"
+ ],
+ "version": "==3.0.4"
+ },
+ "idna": {
+ "hashes": [
+ "sha256:cc19709fd6d0cbfed39ea875d29ba6d4e22c0cebc510a76d6302a28385e8bb70",
+ "sha256:3cb5ce08046c4e3a560fc02f138d0ac63e00f8ce5901a56b32ec8b7994082aab"
+ ],
+ "version": "==2.5"
+ },
+ "requests": "==2.18.0",
+ "urllib3": {
+ "hashes": [
+ "sha256:8ed6d5c1ff9d6ba84677310060d6a3a78ca3072ce0684cb3c645023009c114b1",
+ "sha256:b14486978518ca0901a76ba973d7821047409d7f726f22156b24e83fd71382a5"
+ ],
+ "version": "==1.21.1"
+ }
+ },
+ "develop": {
+ "py": {
+ "hashes": [
+ "sha256:8cca5c229d225f8c1e3085be4fcf306090b00850fefad892f9d96c7b6e2f310f",
+ "sha256:ca18943e28235417756316bfada6cd96b23ce60dd532642690dcfdaba988a76d"
+ ],
+ "version": "==1.5.2"
+ },
+ "pytest": ["some", "random", "stuff"]
+ }
+}
diff --git a/uv/spec/fixtures/pipfile_files/edited_array.lock b/uv/spec/fixtures/pipfile_files/edited_array.lock
new file mode 100644
index 00000000000..d7681e25ddf
--- /dev/null
+++ b/uv/spec/fixtures/pipfile_files/edited_array.lock
@@ -0,0 +1,56 @@
+{
+ "_meta": {
+ "hash": {
+ "sha256": "c402ea48092e9d467af51a483bb8dd8ad0620e11c94f009dcd433f97a99d45db"
+ },
+ "pipfile-spec": 6,
+ "requires": {},
+ "sources": [
+ {
+ "url": "https://pypi.org/simple",
+ "verify_ssl": true
+ }
+ ]
+ },
+ "default": {
+ "certifi": {
+ "hashes": [
+ "sha256:244be0d93b71e93fc0a0a479862051414d0e00e16435707e5bf5000f92e04694",
+ "sha256:5ec74291ca1136b40f0379e1128ff80e866597e4e2c1e755739a913bbc3613c0"
+ ],
+ "version": "==2017.11.5"
+ },
+ "chardet": {
+ "hashes": [
+ "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691",
+ "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae"
+ ],
+ "version": "==3.0.4"
+ },
+ "idna": {
+ "hashes": [
+ "sha256:cc19709fd6d0cbfed39ea875d29ba6d4e22c0cebc510a76d6302a28385e8bb70",
+ "sha256:3cb5ce08046c4e3a560fc02f138d0ac63e00f8ce5901a56b32ec8b7994082aab"
+ ],
+ "version": "==2.5"
+ },
+ "requests": ["garbage"],
+ "urllib3": {
+ "hashes": [
+ "sha256:8ed6d5c1ff9d6ba84677310060d6a3a78ca3072ce0684cb3c645023009c114b1",
+ "sha256:b14486978518ca0901a76ba973d7821047409d7f726f22156b24e83fd71382a5"
+ ],
+ "version": "==1.21.1"
+ }
+ },
+ "develop": {
+ "py": {
+ "hashes": [
+ "sha256:8cca5c229d225f8c1e3085be4fcf306090b00850fefad892f9d96c7b6e2f310f",
+ "sha256:ca18943e28235417756316bfada6cd96b23ce60dd532642690dcfdaba988a76d"
+ ],
+ "version": "==1.5.2"
+ },
+ "pytest": ["some", "random", "stuff"]
+ }
+}
diff --git a/uv/spec/fixtures/pipfile_files/empty_requirement b/uv/spec/fixtures/pipfile_files/empty_requirement
new file mode 100644
index 00000000000..174b9b6b1b1
--- /dev/null
+++ b/uv/spec/fixtures/pipfile_files/empty_requirement
@@ -0,0 +1,8 @@
+[[source]]
+name = "pypi"
+url = "https://pypi.org/simple"
+verify_ssl = true
+
+[dev-packages]
+tenacity = "*"
+tensorflow-gpu = ""
diff --git a/uv/spec/fixtures/pipfile_files/environment_variable_source b/uv/spec/fixtures/pipfile_files/environment_variable_source
new file mode 100644
index 00000000000..44b76979eab
--- /dev/null
+++ b/uv/spec/fixtures/pipfile_files/environment_variable_source
@@ -0,0 +1,10 @@
+[[source]]
+name = "pypi"
+url = "https://pypi.org/${ENV_VAR}"
+verify_ssl = true
+
+[dev-packages]
+pytest = "==3.4.0"
+
+[packages]
+requests = "==2.18.0"
diff --git a/uv/spec/fixtures/pipfile_files/environment_variable_source.lock b/uv/spec/fixtures/pipfile_files/environment_variable_source.lock
new file mode 100644
index 00000000000..e3ebcbabbc3
--- /dev/null
+++ b/uv/spec/fixtures/pipfile_files/environment_variable_source.lock
@@ -0,0 +1,88 @@
+{
+ "_meta": {
+ "hash": {
+ "sha256": "60e573c7eb5986a35673614ffd23a685f76846f0ac9f4fa4a4577377e98545a6"
+ },
+ "pipfile-spec": 6,
+ "requires": {},
+ "sources": [
+ {
+ "url": "https://pypi.org/${ENV_VAR}",
+ "verify_ssl": true
+ }
+ ]
+ },
+ "default": {
+ "certifi": {
+ "hashes": [
+ "sha256:14131608ad2fd56836d33a71ee60fa1c82bc9d2c8d98b7bdbc631fe1b3cd1296",
+ "sha256:edbc3f203427eef571f79a7692bb160a2b0f7ccaa31953e99bd17e307cf63f7d"
+ ],
+ "version": "==2018.1.18"
+ },
+ "chardet": {
+ "hashes": [
+ "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691",
+ "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae"
+ ],
+ "version": "==3.0.4"
+ },
+ "idna": {
+ "hashes": [
+ "sha256:cc19709fd6d0cbfed39ea875d29ba6d4e22c0cebc510a76d6302a28385e8bb70",
+ "sha256:3cb5ce08046c4e3a560fc02f138d0ac63e00f8ce5901a56b32ec8b7994082aab"
+ ],
+ "version": "==2.5"
+ },
+ "requests": {
+ "hashes": [
+ "sha256:5e88d64aa56ac0fda54e77fb9762ebc65879e171b746d5479a33c4082519d6c6",
+ "sha256:cd0189f962787284bff715fddaad478eb4d9c15aa167bd64e52ea0f661e7ea5c"
+ ],
+ "version": "==2.18.0"
+ },
+ "urllib3": {
+ "hashes": [
+ "sha256:8ed6d5c1ff9d6ba84677310060d6a3a78ca3072ce0684cb3c645023009c114b1",
+ "sha256:b14486978518ca0901a76ba973d7821047409d7f726f22156b24e83fd71382a5"
+ ],
+ "version": "==1.21.1"
+ }
+ },
+ "develop": {
+ "attrs": {
+ "hashes": [
+ "sha256:a17a9573a6f475c99b551c0e0a812707ddda1ec9653bed04c13841404ed6f450",
+ "sha256:1c7960ccfd6a005cd9f7ba884e6316b5e430a3f1a6c37c5f87d8b43f83b54ec9"
+ ],
+ "version": "==17.4.0"
+ },
+ "pluggy": {
+ "hashes": [
+ "sha256:7f8ae7f5bdf75671a718d2daf0a64b7885f74510bcd98b1a0bb420eb9a9d0cff"
+ ],
+ "version": "==0.6.0"
+ },
+ "py": {
+ "hashes": [
+ "sha256:8cca5c229d225f8c1e3085be4fcf306090b00850fefad892f9d96c7b6e2f310f",
+ "sha256:ca18943e28235417756316bfada6cd96b23ce60dd532642690dcfdaba988a76d"
+ ],
+ "version": "==1.5.2"
+ },
+ "pytest": {
+ "hashes": [
+ "sha256:95fa025cd6deb5d937e04e368a00552332b58cae23f63b76c8c540ff1733ab6d",
+ "sha256:6074ea3b9c999bd6d0df5fa9d12dd95ccd23550df2a582f5f5b848331d2e82ca"
+ ],
+ "version": "==3.4.0"
+ },
+ "six": {
+ "hashes": [
+ "sha256:832dc0e10feb1aa2c68dcc57dbb658f1c7e65b9b61af69048abc87a2db00a0eb",
+ "sha256:70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9"
+ ],
+ "version": "==1.11.0"
+ }
+ }
+}
diff --git a/uv/spec/fixtures/pipfile_files/environment_variable_verify_ssl_false b/uv/spec/fixtures/pipfile_files/environment_variable_verify_ssl_false
new file mode 100644
index 00000000000..da16502b2b3
--- /dev/null
+++ b/uv/spec/fixtures/pipfile_files/environment_variable_verify_ssl_false
@@ -0,0 +1,10 @@
+[[source]]
+name = "pypi"
+url = "https://pypi.org/${ENV_VAR}"
+verify_ssl = false
+
+[dev-packages]
+pytest = "==3.4.0"
+
+[packages]
+requests = "==2.18.0"
diff --git a/uv/spec/fixtures/pipfile_files/environment_variable_verify_ssl_false.lock b/uv/spec/fixtures/pipfile_files/environment_variable_verify_ssl_false.lock
new file mode 100644
index 00000000000..e3ebcbabbc3
--- /dev/null
+++ b/uv/spec/fixtures/pipfile_files/environment_variable_verify_ssl_false.lock
@@ -0,0 +1,88 @@
+{
+ "_meta": {
+ "hash": {
+ "sha256": "60e573c7eb5986a35673614ffd23a685f76846f0ac9f4fa4a4577377e98545a6"
+ },
+ "pipfile-spec": 6,
+ "requires": {},
+ "sources": [
+ {
+ "url": "https://pypi.org/${ENV_VAR}",
+ "verify_ssl": true
+ }
+ ]
+ },
+ "default": {
+ "certifi": {
+ "hashes": [
+ "sha256:14131608ad2fd56836d33a71ee60fa1c82bc9d2c8d98b7bdbc631fe1b3cd1296",
+ "sha256:edbc3f203427eef571f79a7692bb160a2b0f7ccaa31953e99bd17e307cf63f7d"
+ ],
+ "version": "==2018.1.18"
+ },
+ "chardet": {
+ "hashes": [
+ "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691",
+ "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae"
+ ],
+ "version": "==3.0.4"
+ },
+ "idna": {
+ "hashes": [
+ "sha256:cc19709fd6d0cbfed39ea875d29ba6d4e22c0cebc510a76d6302a28385e8bb70",
+ "sha256:3cb5ce08046c4e3a560fc02f138d0ac63e00f8ce5901a56b32ec8b7994082aab"
+ ],
+ "version": "==2.5"
+ },
+ "requests": {
+ "hashes": [
+ "sha256:5e88d64aa56ac0fda54e77fb9762ebc65879e171b746d5479a33c4082519d6c6",
+ "sha256:cd0189f962787284bff715fddaad478eb4d9c15aa167bd64e52ea0f661e7ea5c"
+ ],
+ "version": "==2.18.0"
+ },
+ "urllib3": {
+ "hashes": [
+ "sha256:8ed6d5c1ff9d6ba84677310060d6a3a78ca3072ce0684cb3c645023009c114b1",
+ "sha256:b14486978518ca0901a76ba973d7821047409d7f726f22156b24e83fd71382a5"
+ ],
+ "version": "==1.21.1"
+ }
+ },
+ "develop": {
+ "attrs": {
+ "hashes": [
+ "sha256:a17a9573a6f475c99b551c0e0a812707ddda1ec9653bed04c13841404ed6f450",
+ "sha256:1c7960ccfd6a005cd9f7ba884e6316b5e430a3f1a6c37c5f87d8b43f83b54ec9"
+ ],
+ "version": "==17.4.0"
+ },
+ "pluggy": {
+ "hashes": [
+ "sha256:7f8ae7f5bdf75671a718d2daf0a64b7885f74510bcd98b1a0bb420eb9a9d0cff"
+ ],
+ "version": "==0.6.0"
+ },
+ "py": {
+ "hashes": [
+ "sha256:8cca5c229d225f8c1e3085be4fcf306090b00850fefad892f9d96c7b6e2f310f",
+ "sha256:ca18943e28235417756316bfada6cd96b23ce60dd532642690dcfdaba988a76d"
+ ],
+ "version": "==1.5.2"
+ },
+ "pytest": {
+ "hashes": [
+ "sha256:95fa025cd6deb5d937e04e368a00552332b58cae23f63b76c8c540ff1733ab6d",
+ "sha256:6074ea3b9c999bd6d0df5fa9d12dd95ccd23550df2a582f5f5b848331d2e82ca"
+ ],
+ "version": "==3.4.0"
+ },
+ "six": {
+ "hashes": [
+ "sha256:832dc0e10feb1aa2c68dcc57dbb658f1c7e65b9b61af69048abc87a2db00a0eb",
+ "sha256:70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9"
+ ],
+ "version": "==1.11.0"
+ }
+ }
+}
diff --git a/uv/spec/fixtures/pipfile_files/exact_version b/uv/spec/fixtures/pipfile_files/exact_version
new file mode 100644
index 00000000000..aaa0096585f
--- /dev/null
+++ b/uv/spec/fixtures/pipfile_files/exact_version
@@ -0,0 +1,10 @@
+[[source]]
+name = "pypi"
+url = "https://pypi.org/simple"
+verify_ssl = true
+
+[dev-packages]
+Pytest = "==3.4.0"
+
+[packages]
+Requests = "==2.18.0"
diff --git a/uv/spec/fixtures/pipfile_files/exact_version.lock b/uv/spec/fixtures/pipfile_files/exact_version.lock
new file mode 100644
index 00000000000..8a0dcf8792a
--- /dev/null
+++ b/uv/spec/fixtures/pipfile_files/exact_version.lock
@@ -0,0 +1,100 @@
+{
+ "_meta": {
+ "hash": {
+ "sha256": "40d0c95e8f178554fbb42aee3b2e2dee2241acccb5974362f806958d273f53d1"
+ },
+ "pipfile-spec": 6,
+ "requires": {},
+ "sources": [
+ {
+ "url": "https://pypi.org/simple",
+ "verify_ssl": true
+ }
+ ]
+ },
+ "default": {
+ "certifi": {
+ "hashes": [
+ "sha256:13e698f54293db9f89122b0581843a782ad0934a4fe0172d2a980ba77fc61bb7",
+ "sha256:9fa520c1bacfb634fa7af20a76bcbd3d5fb390481724c597da32c719a7dca4b0"
+ ],
+ "version": "==2018.4.16"
+ },
+ "chardet": {
+ "hashes": [
+ "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae",
+ "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"
+ ],
+ "version": "==3.0.4"
+ },
+ "idna": {
+ "hashes": [
+ "sha256:3cb5ce08046c4e3a560fc02f138d0ac63e00f8ce5901a56b32ec8b7994082aab",
+ "sha256:cc19709fd6d0cbfed39ea875d29ba6d4e22c0cebc510a76d6302a28385e8bb70"
+ ],
+ "version": "==2.5"
+ },
+ "requests": {
+ "hashes": [
+ "sha256:5e88d64aa56ac0fda54e77fb9762ebc65879e171b746d5479a33c4082519d6c6",
+ "sha256:cd0189f962787284bff715fddaad478eb4d9c15aa167bd64e52ea0f661e7ea5c"
+ ],
+ "index": "pypi",
+ "version": "==2.18.0"
+ },
+ "urllib3": {
+ "hashes": [
+ "sha256:8ed6d5c1ff9d6ba84677310060d6a3a78ca3072ce0684cb3c645023009c114b1",
+ "sha256:b14486978518ca0901a76ba973d7821047409d7f726f22156b24e83fd71382a5"
+ ],
+ "version": "==1.21.1"
+ }
+ },
+ "develop": {
+ "attrs": {
+ "hashes": [
+ "sha256:4b90b09eeeb9b88c35bc642cbac057e45a5fd85367b985bd2809c62b7b939265",
+ "sha256:e0d0eb91441a3b53dab4d9b743eafc1ac44476296a2053b6ca3af0b139faf87b"
+ ],
+ "version": "==18.1.0"
+ },
+ "funcsigs": {
+ "hashes": [
+ "sha256:330cc27ccbf7f1e992e69fef78261dc7c6569012cf397db8d3de0234e6c937ca",
+ "sha256:a7bb0f2cf3a3fd1ab2732cb49eba4252c2af4240442415b4abce3b87022a8f50"
+ ],
+ "markers": "python_version < '3.0'",
+ "version": "==1.0.2"
+ },
+ "pluggy": {
+ "hashes": [
+ "sha256:7f8ae7f5bdf75671a718d2daf0a64b7885f74510bcd98b1a0bb420eb9a9d0cff",
+ "sha256:d345c8fe681115900d6da8d048ba67c25df42973bda370783cd58826442dcd7c",
+ "sha256:e160a7fcf25762bb60efc7e171d4497ff1d8d2d75a3d0df7a21b76821ecbf5c5"
+ ],
+ "version": "==0.6.0"
+ },
+ "py": {
+ "hashes": [
+ "sha256:29c9fab495d7528e80ba1e343b958684f4ace687327e6f789a94bf3d1915f881",
+ "sha256:983f77f3331356039fdd792e9220b7b8ee1aa6bd2b25f567a963ff1de5a64f6a"
+ ],
+ "version": "==1.5.3"
+ },
+ "pytest": {
+ "hashes": [
+ "sha256:6074ea3b9c999bd6d0df5fa9d12dd95ccd23550df2a582f5f5b848331d2e82ca",
+ "sha256:95fa025cd6deb5d937e04e368a00552332b58cae23f63b76c8c540ff1733ab6d"
+ ],
+ "index": "pypi",
+ "version": "==3.4.0"
+ },
+ "six": {
+ "hashes": [
+ "sha256:70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9",
+ "sha256:832dc0e10feb1aa2c68dcc57dbb658f1c7e65b9b61af69048abc87a2db00a0eb"
+ ],
+ "version": "==1.11.0"
+ }
+ }
+}
diff --git a/uv/spec/fixtures/pipfile_files/extra_subdependency b/uv/spec/fixtures/pipfile_files/extra_subdependency
new file mode 100644
index 00000000000..58ee60c2682
--- /dev/null
+++ b/uv/spec/fixtures/pipfile_files/extra_subdependency
@@ -0,0 +1,8 @@
+[[source]]
+name = "pypi"
+url = "https://pypi.org/simple"
+verify_ssl = true
+
+[packages]
+flask = "==1.0.*"
+raven = {extras = ["flask"], version = "==5.27.1"}
diff --git a/uv/spec/fixtures/pipfile_files/extra_subdependency.lock b/uv/spec/fixtures/pipfile_files/extra_subdependency.lock
new file mode 100644
index 00000000000..b4617324dac
--- /dev/null
+++ b/uv/spec/fixtures/pipfile_files/extra_subdependency.lock
@@ -0,0 +1,83 @@
+{
+ "_meta": {
+ "hash": {
+ "sha256": "13641ee824a50a1893e8cab488fc1d84789815c0c1c89fac41a023ecd073cc76"
+ },
+ "pipfile-spec": 6,
+ "requires": {
+ "python_version": "2.7"
+ },
+ "sources": [
+ {
+ "name": "pypi",
+ "url": "https://pypi.org/simple",
+ "verify_ssl": true
+ }
+ ]
+ },
+ "default": {
+ "blinker": {
+ "hashes": [
+ "sha256:471aee25f3992bd325afa3772f1063dbdbbca947a041b8b89466dc00d606f8b6"
+ ],
+ "version": "==1.4"
+ },
+ "click": {
+ "hashes": [
+ "sha256:29f99fc6125fbc931b758dc053b3114e55c77a6e4c6c3a2674a2dc986016381d",
+ "sha256:f15516df478d5a56180fbf80e68f206010e6d160fc39fa508b65e035fd75130b"
+ ],
+ "version": "==6.7"
+ },
+ "contextlib2": {
+ "hashes": [
+ "sha256:509f9419ee91cdd00ba34443217d5ca51f5a364a404e1dce9e8979cea969ca48",
+ "sha256:f5260a6e679d2ff42ec91ec5252f4eeffdcf21053db9113bd0a8e4d953769c00"
+ ],
+ "version": "==0.5.5"
+ },
+ "flask": {
+ "hashes": [
+ "sha256:cfc15b45622f9cfee6b5803723070fd0f489b3bd662179195e702cb95fd924c8",
+ "sha256:dbe2a9f539f4d0fe26fa44c08d6e556e2a4a4dd3a3fb0550f39954cf57571363"
+ ],
+ "index": "pypi",
+ "version": "==1.0.1"
+ },
+ "itsdangerous": {
+ "hashes": [
+ "sha256:cbb3fcf8d3e33df861709ecaf89d9e6629cff0a217bc2848f1b41cd30d360519"
+ ],
+ "version": "==0.24"
+ },
+ "jinja2": {
+ "hashes": [
+ "sha256:74c935a1b8bb9a3947c50a54766a969d4846290e1e788ea44c1392163723c3bd",
+ "sha256:f84be1bb0040caca4cea721fcbbbbd61f9be9464ca236387158b0feea01914a4"
+ ],
+ "version": "==2.10"
+ },
+ "markupsafe": {
+ "hashes": [
+ "sha256:a6be69091dac236ea9c6bc7d012beab42010fa914c459791d627dad4910eb665"
+ ],
+ "version": "==1.0"
+ },
+ "raven": {
+ "hashes": [
+ "sha256:1a7b595391c4557d8a9d9245138158130e43dcad02757f18d0a458e55c1e7162",
+ "sha256:6d98c03c789e2d15dc61992e5e2c1ef0018c467d3ce7b9aa5830e7940a77b69a"
+ ],
+ "index": "pypi",
+ "version": "==5.27.1"
+ },
+ "werkzeug": {
+ "hashes": [
+ "sha256:c3fd7a7d41976d9f44db327260e263132466836cef6f91512889ed60ad26557c",
+ "sha256:d5da73735293558eb1651ee2fddc4d0dedcfa06538b8813a2e20011583c9e49b"
+ ],
+ "version": "==0.14.1"
+ }
+ },
+ "develop": {}
+}
diff --git a/uv/spec/fixtures/pipfile_files/git_source b/uv/spec/fixtures/pipfile_files/git_source
new file mode 100644
index 00000000000..827aaedbbcb
--- /dev/null
+++ b/uv/spec/fixtures/pipfile_files/git_source
@@ -0,0 +1,8 @@
+[[source]]
+name = "pypi"
+url = "https://pypi.org/simple"
+verify_ssl = true
+
+[packages]
+requests = "*"
+pythonfinder = { git = 'https://github.com/sarugaku/pythonfinder.git', ref = 'v0.1.2' }
diff --git a/uv/spec/fixtures/pipfile_files/git_source.lock b/uv/spec/fixtures/pipfile_files/git_source.lock
new file mode 100644
index 00000000000..c72b18fcb8a
--- /dev/null
+++ b/uv/spec/fixtures/pipfile_files/git_source.lock
@@ -0,0 +1,57 @@
+{
+ "_meta": {
+ "hash": {
+ "sha256": "ab083473c9e4abf940ab40d0b5e2882d1d69cf2e8b3739e21131f90ffde8c04f"
+ },
+ "pipfile-spec": 6,
+ "requires": {},
+ "sources": [
+ {
+ "url": "https://pypi.org/simple",
+ "verify_ssl": true
+ }
+ ]
+ },
+ "default": {
+ "certifi": {
+ "hashes": [
+ "sha256:244be0d93b71e93fc0a0a479862051414d0e00e16435707e5bf5000f92e04694",
+ "sha256:5ec74291ca1136b40f0379e1128ff80e866597e4e2c1e755739a913bbc3613c0"
+ ],
+ "version": "==2017.11.5"
+ },
+ "chardet": {
+ "hashes": [
+ "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691",
+ "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae"
+ ],
+ "version": "==3.0.4"
+ },
+ "idna": {
+ "hashes": [
+ "sha256:8c7309c718f94b3a625cb648ace320157ad16ff131ae0af362c9f21b80ef6ec4",
+ "sha256:2c6a5de3089009e3da7c5dde64a141dbc8551d5b7f6cf4ed7c2568d0cc520a8f"
+ ],
+ "version": "==2.6"
+ },
+ "pythonfinder": {
+ "git": "https://github.com/sarugaku/pythonfinder.git",
+ "ref": "e63ef4351b3a2757c374cd1b828a1adef87bb15e"
+ },
+ "requests": {
+ "hashes": [
+ "sha256:6a1b267aa90cac58ac3a765d067950e7dbbf75b1da07e895d1f594193a40a38b",
+ "sha256:9c443e7324ba5b85070c4a818ade28bfabedf16ea10206da1132edaa6dda237e"
+ ],
+ "version": "==2.18.4"
+ },
+ "urllib3": {
+ "hashes": [
+ "sha256:06330f386d6e4b195fbfc736b297f58c5a892e4440e54d294d7004e3a9bbea1b",
+ "sha256:cc44da8e1145637334317feebd728bd869a35285b93cbb4cca2577da7e62db4f"
+ ],
+ "version": "==1.22"
+ }
+ },
+ "develop": {}
+}
diff --git a/uv/spec/fixtures/pipfile_files/git_source_bad_ref b/uv/spec/fixtures/pipfile_files/git_source_bad_ref
new file mode 100644
index 00000000000..b3ca7d30023
--- /dev/null
+++ b/uv/spec/fixtures/pipfile_files/git_source_bad_ref
@@ -0,0 +1,8 @@
+[[source]]
+name = "pypi"
+url = "https://pypi.org/simple"
+verify_ssl = true
+
+[packages]
+requests = "*"
+pythonfinder = { git = 'https://github.com/sarugaku/pythonfinder.git', ref = 'v15.1.2' }
diff --git a/uv/spec/fixtures/pipfile_files/git_source_bad_ref.lock b/uv/spec/fixtures/pipfile_files/git_source_bad_ref.lock
new file mode 100644
index 00000000000..d869d20877c
--- /dev/null
+++ b/uv/spec/fixtures/pipfile_files/git_source_bad_ref.lock
@@ -0,0 +1,57 @@
+{
+ "_meta": {
+ "hash": {
+ "sha256": "76257e8b1a36ef923d9e0a4f4b3c06ab5bdb727ff0b05b700d24c105bca0c9f3"
+ },
+ "pipfile-spec": 6,
+ "requires": {},
+ "sources": [
+ {
+ "url": "https://pypi.org/simple",
+ "verify_ssl": true
+ }
+ ]
+ },
+ "default": {
+ "certifi": {
+ "hashes": [
+ "sha256:244be0d93b71e93fc0a0a479862051414d0e00e16435707e5bf5000f92e04694",
+ "sha256:5ec74291ca1136b40f0379e1128ff80e866597e4e2c1e755739a913bbc3613c0"
+ ],
+ "version": "==2017.11.5"
+ },
+ "chardet": {
+ "hashes": [
+ "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691",
+ "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae"
+ ],
+ "version": "==3.0.4"
+ },
+ "idna": {
+ "hashes": [
+ "sha256:8c7309c718f94b3a625cb648ace320157ad16ff131ae0af362c9f21b80ef6ec4",
+ "sha256:2c6a5de3089009e3da7c5dde64a141dbc8551d5b7f6cf4ed7c2568d0cc520a8f"
+ ],
+ "version": "==2.6"
+ },
+ "pythonfinder": {
+ "git": "https://github.com/sarugaku/pythonfinder.git",
+ "ref": "v15.1.2"
+ },
+ "requests": {
+ "hashes": [
+ "sha256:6a1b267aa90cac58ac3a765d067950e7dbbf75b1da07e895d1f594193a40a38b",
+ "sha256:9c443e7324ba5b85070c4a818ade28bfabedf16ea10206da1132edaa6dda237e"
+ ],
+ "version": "==2.18.4"
+ },
+ "urllib3": {
+ "hashes": [
+ "sha256:06330f386d6e4b195fbfc736b297f58c5a892e4440e54d294d7004e3a9bbea1b",
+ "sha256:cc44da8e1145637334317feebd728bd869a35285b93cbb4cca2577da7e62db4f"
+ ],
+ "version": "==1.22"
+ }
+ },
+ "develop": {}
+}
diff --git a/uv/spec/fixtures/pipfile_files/git_source_no_ref b/uv/spec/fixtures/pipfile_files/git_source_no_ref
new file mode 100644
index 00000000000..24966cbc35d
--- /dev/null
+++ b/uv/spec/fixtures/pipfile_files/git_source_no_ref
@@ -0,0 +1,8 @@
+[[source]]
+name = "pypi"
+url = "https://pypi.org/simple"
+verify_ssl = true
+
+[packages]
+requests = "*"
+pythonfinder = { git = 'https://github.com/sarugaku/pythonfinder.git' }
diff --git a/uv/spec/fixtures/pipfile_files/git_source_no_ref.lock b/uv/spec/fixtures/pipfile_files/git_source_no_ref.lock
new file mode 100644
index 00000000000..1e028a9c4b3
--- /dev/null
+++ b/uv/spec/fixtures/pipfile_files/git_source_no_ref.lock
@@ -0,0 +1,58 @@
+{
+ "_meta": {
+ "hash": {
+ "sha256": "96d3c51555fc4d0e5b94540f5f8d85271cfca60e55ebdd7181d9891544691ab2"
+ },
+ "pipfile-spec": 6,
+ "requires": {},
+ "sources": [
+ {
+ "url": "https://pypi.org/simple",
+ "verify_ssl": true
+ }
+ ]
+ },
+ "default": {
+ "certifi": {
+ "hashes": [
+ "sha256:244be0d93b71e93fc0a0a479862051414d0e00e16435707e5bf5000f92e04694",
+ "sha256:5ec74291ca1136b40f0379e1128ff80e866597e4e2c1e755739a913bbc3613c0"
+ ],
+ "version": "==2017.11.5"
+ },
+ "chardet": {
+ "hashes": [
+ "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691",
+ "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae"
+ ],
+ "version": "==3.0.4"
+ },
+ "idna": {
+ "hashes": [
+ "sha256:8c7309c718f94b3a625cb648ace320157ad16ff131ae0af362c9f21b80ef6ec4",
+ "sha256:2c6a5de3089009e3da7c5dde64a141dbc8551d5b7f6cf4ed7c2568d0cc520a8f"
+ ],
+ "version": "==2.6"
+ },
+ "pythonfinder": {
+ "git": "https://github.com/sarugaku/pythonfinder.git",
+ "markers": "python_version >= '3.7'",
+ "ref": "9ee85b83290850f99dec2c0ec58a084305047347"
+ },
+ "requests": {
+ "hashes": [
+ "sha256:6a1b267aa90cac58ac3a765d067950e7dbbf75b1da07e895d1f594193a40a38b",
+ "sha256:9c443e7324ba5b85070c4a818ade28bfabedf16ea10206da1132edaa6dda237e"
+ ],
+ "version": "==2.18.4"
+ },
+ "urllib3": {
+ "hashes": [
+ "sha256:06330f386d6e4b195fbfc736b297f58c5a892e4440e54d294d7004e3a9bbea1b",
+ "sha256:cc44da8e1145637334317feebd728bd869a35285b93cbb4cca2577da7e62db4f"
+ ],
+ "version": "==1.22"
+ }
+ },
+ "develop": {}
+}
diff --git a/uv/spec/fixtures/pipfile_files/git_source_unreachable b/uv/spec/fixtures/pipfile_files/git_source_unreachable
new file mode 100644
index 00000000000..4df40330391
--- /dev/null
+++ b/uv/spec/fixtures/pipfile_files/git_source_unreachable
@@ -0,0 +1,8 @@
+[[source]]
+name = "pypi"
+url = "https://pypi.org/simple"
+verify_ssl = true
+
+[packages]
+requests = "*"
+django = { git = 'https://github.com/user/django.git', ref = '1.11.4' }
diff --git a/uv/spec/fixtures/pipfile_files/git_source_unreachable.lock b/uv/spec/fixtures/pipfile_files/git_source_unreachable.lock
new file mode 100644
index 00000000000..dd0690f87c3
--- /dev/null
+++ b/uv/spec/fixtures/pipfile_files/git_source_unreachable.lock
@@ -0,0 +1,57 @@
+{
+ "_meta": {
+ "hash": {
+ "sha256": "76257e8b1a36ef923d9e0a4f4b3c06ab5bdb727ff0b05b700d24c105bca0c9f3"
+ },
+ "pipfile-spec": 6,
+ "requires": {},
+ "sources": [
+ {
+ "url": "https://pypi.org/simple",
+ "verify_ssl": true
+ }
+ ]
+ },
+ "default": {
+ "certifi": {
+ "hashes": [
+ "sha256:244be0d93b71e93fc0a0a479862051414d0e00e16435707e5bf5000f92e04694",
+ "sha256:5ec74291ca1136b40f0379e1128ff80e866597e4e2c1e755739a913bbc3613c0"
+ ],
+ "version": "==2017.11.5"
+ },
+ "chardet": {
+ "hashes": [
+ "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691",
+ "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae"
+ ],
+ "version": "==3.0.4"
+ },
+ "django": {
+ "git": "https://github.com/user/django.git",
+ "ref": "1.11.4"
+ },
+ "idna": {
+ "hashes": [
+ "sha256:8c7309c718f94b3a625cb648ace320157ad16ff131ae0af362c9f21b80ef6ec4",
+ "sha256:2c6a5de3089009e3da7c5dde64a141dbc8551d5b7f6cf4ed7c2568d0cc520a8f"
+ ],
+ "version": "==2.6"
+ },
+ "requests": {
+ "hashes": [
+ "sha256:6a1b267aa90cac58ac3a765d067950e7dbbf75b1da07e895d1f594193a40a38b",
+ "sha256:9c443e7324ba5b85070c4a818ade28bfabedf16ea10206da1132edaa6dda237e"
+ ],
+ "version": "==2.18.4"
+ },
+ "urllib3": {
+ "hashes": [
+ "sha256:06330f386d6e4b195fbfc736b297f58c5a892e4440e54d294d7004e3a9bbea1b",
+ "sha256:cc44da8e1145637334317feebd728bd869a35285b93cbb4cca2577da7e62db4f"
+ ],
+ "version": "==1.22"
+ }
+ },
+ "develop": {}
+}
diff --git a/uv/spec/fixtures/pipfile_files/hard_names b/uv/spec/fixtures/pipfile_files/hard_names
new file mode 100644
index 00000000000..840fb65bd6a
--- /dev/null
+++ b/uv/spec/fixtures/pipfile_files/hard_names
@@ -0,0 +1,12 @@
+[[source]]
+name = "pypi"
+url = "https://pypi.org/simple"
+verify_ssl = true
+
+[dev-packages]
+Pytest = "==3.4.0"
+
+[packages]
+Requests = "==2.18.0"
+python_decouple = "==3.1"
+"discord.py" = "==0.16.1"
diff --git a/uv/spec/fixtures/pipfile_files/hard_names.lock b/uv/spec/fixtures/pipfile_files/hard_names.lock
new file mode 100644
index 00000000000..04ff197918b
--- /dev/null
+++ b/uv/spec/fixtures/pipfile_files/hard_names.lock
@@ -0,0 +1,180 @@
+{
+ "_meta": {
+ "hash": {
+ "sha256": "b35b2b4af6b053fab50a6301d4b2ab00380f258a47dba073de49bb64586d7e7a"
+ },
+ "pipfile-spec": 6,
+ "requires": {},
+ "sources": [
+ {
+ "url": "https://pypi.org/simple",
+ "verify_ssl": true
+ }
+ ]
+ },
+ "default": {
+ "aiohttp": {
+ "hashes": [
+ "sha256:3a253332a0d8f82549e65035ebe7199580c3ea0e47071b7428f25b109b3c0310",
+ "sha256:3ac6fa105355928e2fc02e876d0d72d6230557d4637017ebf09aec7611124155",
+ "sha256:3bfcb76553d7f6296d1a598162d5fb890198f98c021540cbbb85bb604ff198db",
+ "sha256:714c62532ca6be90be4b54002743e7ea277ec78b45f04ae86cdc6f45a8400abd",
+ "sha256:81a6aaace2b9e8a87531277a5d5f998efbd3554c15bf47173834386966d1bbe1",
+ "sha256:ad374a5d7be1de271ecd0fb0ef87c0f8dd9fb062e6fae350fa6c098360018978",
+ "sha256:c3e1897726f97d40e067e8b658b2dbdfe216f32b801c5c589212e1b1f9aa8388",
+ "sha256:c579ec606f25b3f756f177fee6db344f8d7ef75cfc0603a94c9fa1d1c645789d",
+ "sha256:e1985766a4c83fcbdf7dde06544231fc9fb3de8929788179e623d6f9f9f321d2"
+ ],
+ "version": "==1.0.5"
+ },
+ "async-timeout": {
+ "hashes": [
+ "sha256:474d4bc64cee20603e225eb1ece15e248962958b45a3648a9f5cc29e827a610c",
+ "sha256:b3c0ddc416736619bd4a95ca31de8da6920c3b9a140c64dbef2b2fa7bf521287"
+ ],
+ "version": "==3.0.0"
+ },
+ "certifi": {
+ "hashes": [
+ "sha256:14131608ad2fd56836d33a71ee60fa1c82bc9d2c8d98b7bdbc631fe1b3cd1296",
+ "sha256:edbc3f203427eef571f79a7692bb160a2b0f7ccaa31953e99bd17e307cf63f7d"
+ ],
+ "version": "==2018.1.18"
+ },
+ "chardet": {
+ "hashes": [
+ "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691",
+ "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae"
+ ],
+ "version": "==3.0.4"
+ },
+ "discord.py": {
+ "hashes": [
+ "sha256:224c2ae10b2991cf7b5cbb77107b82b203b07a7bb43fdeab652a4ae69fecb24c"
+ ],
+ "version": "==0.16.1"
+ },
+ "idna": {
+ "hashes": [
+ "sha256:cc19709fd6d0cbfed39ea875d29ba6d4e22c0cebc510a76d6302a28385e8bb70",
+ "sha256:3cb5ce08046c4e3a560fc02f138d0ac63e00f8ce5901a56b32ec8b7994082aab"
+ ],
+ "version": "==2.5"
+ },
+ "multidict": {
+ "hashes": [
+ "sha256:112eeeddd226af681dc82b756ed34aa7b6d98f9c4a15760050298c21d715473d",
+ "sha256:13b64ecb692effcabc5e29569ba9b5eb69c35112f990a16d6833ec3a9d9f8ec0",
+ "sha256:1725373fb8f18c2166f8e0e5789851ccf98453c849b403945fa4ef59a16ca44e",
+ "sha256:2061a50b7cae60a1f987503a995b2fc38e47027a937a355a124306ed9c629041",
+ "sha256:35b062288a9a478f627c520fd27983160fc97591017d170f966805b428d17e07",
+ "sha256:467b134bcc227b91b8e2ef8d2931f28b50bf7eb7a04c0403d102ded22e66dbfc",
+ "sha256:475a3ece8bb450e49385414ebfae7f8fdb33f62f1ac0c12935c1cfb1b7c1076a",
+ "sha256:49b885287e227a24545a1126d9ac17ae43138610713dc6219b781cc0ad5c6dfc",
+ "sha256:4c95b2725592adb5c46642be2875c1234c32af841732c5504c17726b92082021",
+ "sha256:4ea7ed00f4be0f7335c9a2713a65ac3d986be789ce5ebc10821da9664cbe6b85",
+ "sha256:5e2d5e1d999e941b4a626aea46bdc4206877cf727107fdaa9d46a8a773a6e49b",
+ "sha256:8039c520ef7bb9ec7c3db3df14c570be6362f43c200ae9854d2422d4ffe175a4",
+ "sha256:81459a0ebcca09c1fcb8fe887ed13cf267d9b60fe33718fc5fd1a2a1ab49470a",
+ "sha256:847c3b7b9ca3268e883685dc1347a4d09f84de7bd7597310044d847590447492",
+ "sha256:8551d1db45f0ca4e8ec99130767009a29a4e0dc6558a4a6808491bcd3472d325",
+ "sha256:8fa7679ffe615e0c1c7b80946ab4194669be74848719adf2d7867b5e861eb073",
+ "sha256:a42a36f09f0f907579ff0fde547f2fde8a739a69efe4a2728835979d2bb5e17b",
+ "sha256:a5fcad0070685c5b2d04b468bf5f4c735f5c176432f495ad055fcc4bc0a79b23",
+ "sha256:ae22195b2a7494619b73c01129ddcddc0dfaa9e42727404b1d9a77253da3f420",
+ "sha256:b360e82bdbbd862e1ce2a41cc3bbd0ab614350e813ca74801b34aac0f73465aa",
+ "sha256:b96417899344c5e96bef757f4963a72d02e52653a4e0f99bbea3a531cedac59f",
+ "sha256:b9e921140b797093edfc13ac08dc2a4fd016dd711dc42bb0e1aaf180e48425a7",
+ "sha256:c5022b94fc330e6d177f3eb38097fb52c7df96ca0e04842c068cf0d9fc38b1e6",
+ "sha256:cf2b117f2a8d951638efc7592fb72d3eeb2d38cc2194c26ba7f00e7190451d92",
+ "sha256:d79620b542d9d0e23ae9790ca2fe44f1af40ffad9936efa37bd14954bc3e2818",
+ "sha256:e2860691c11d10dac7c91bddae44f6211b3da4122d9a2ebb509c2247674d6070",
+ "sha256:e3a293553715afecf7e10ea02da40593f9d7f48fe48a74fc5dd3ce08a0c46188",
+ "sha256:e465be3fe7e992e5a6e16731afa6f41cb6ca53afccb4f28ea2fa6457783edf15",
+ "sha256:e6d27895ef922bc859d969452f247bfbe5345d9aba69b9c8dbe1ea7704f0c5d9"
+ ],
+ "version": "==4.4.0"
+ },
+ "python-decouple": {
+ "hashes": [
+ "sha256:1317df14b43efee4337a4aa02914bf004f010cd56d6c4bd894e6474ec8c4fe2d"
+ ],
+ "version": "==3.1"
+ },
+ "requests": {
+ "hashes": [
+ "sha256:5e88d64aa56ac0fda54e77fb9762ebc65879e171b746d5479a33c4082519d6c6",
+ "sha256:cd0189f962787284bff715fddaad478eb4d9c15aa167bd64e52ea0f661e7ea5c"
+ ],
+ "version": "==2.18.0"
+ },
+ "urllib3": {
+ "hashes": [
+ "sha256:8ed6d5c1ff9d6ba84677310060d6a3a78ca3072ce0684cb3c645023009c114b1",
+ "sha256:b14486978518ca0901a76ba973d7821047409d7f726f22156b24e83fd71382a5"
+ ],
+ "version": "==1.21.1"
+ },
+ "websockets": {
+ "hashes": [
+ "sha256:09dfec40e9b73e8808c39ecdbc1733e33915a2b26b90c54566afc0af546a9ec3",
+ "sha256:2aa6d52264cecb08d39741e8fda49f5ac4872aef02617230c84d02e861f3cc5a",
+ "sha256:2f5b7f3920f29609086fb0b63552bb1f86a04b8cbdcc0dbf3775cc90d489dfc8",
+ "sha256:3d38f76f71654268e5533b45df125ff208fee242a102d4b5ca958da5cf5fb345",
+ "sha256:3fcc7dfb365e81ff8206f950c86d1e73accdf3be2f9110c0cb73be32d2e7a9a5",
+ "sha256:4128212ab6f91afda03a0c697add261bdf6946b47928db83f07298ea2cd8d937",
+ "sha256:43e5b9f51dd0000a4c6f646e2ade0c886bd14a784ffac08b9e079bd17a63bcc5",
+ "sha256:4a932c17cb11c361c286c04842dc2385cc7157019bbba8b64808acbc89a95584",
+ "sha256:5ddc5fc121eb76771e990f071071d9530e27d20e8cfb804d9f5823de055837af",
+ "sha256:7347af28fcc70eb45be409760c2a428f8199e7f73c04a621916c3c219ed7ad27",
+ "sha256:85ae1e4b36aa2e90de56d211d2de36d7c093d00277a9afdd9b4f81e69c0214ab",
+ "sha256:8a29100079f5b91a72bcd25d35a7354db985d3babae42d00b9d629f9a0aaa8ac",
+ "sha256:a7e7585c8e3c0f9277ad7d6ee6ccddc69649cd216255d5e255d68f90482aeefa",
+ "sha256:aa42ecef3aed807e23218c264b1e82004cdd131a6698a10b57fc3d8af8f651fc",
+ "sha256:b19e7ede1ba80ee9de6f5b8ccd31beee25402e68bef7c13eeb0b8bc46bc4b7b7",
+ "sha256:c4c5b5ce2d66cb0cf193c14bc9726adca095febef0f7b2c04e5e3fa3487a97a4",
+ "sha256:de743ef26b002efceea7d7756e99e5d38bf5d4f27563b8d27df2a9a5cc57340a",
+ "sha256:e1e568136ad5cb6768504be36d470a136b072acbf3ea882303aee6361be01941",
+ "sha256:e8992f1db371f2a1c5af59e032d9dc7c1aa92f16241efcda695b7d955b4de0c2",
+ "sha256:e9c1cdbb591432c59d0b5ca64fd30b6d517024767f152fc169563b26e7bcc9da"
+ ],
+ "version": "==3.4"
+ }
+ },
+ "develop": {
+ "attrs": {
+ "hashes": [
+ "sha256:a17a9573a6f475c99b551c0e0a812707ddda1ec9653bed04c13841404ed6f450",
+ "sha256:1c7960ccfd6a005cd9f7ba884e6316b5e430a3f1a6c37c5f87d8b43f83b54ec9"
+ ],
+ "version": "==17.4.0"
+ },
+ "pluggy": {
+ "hashes": [
+ "sha256:7f8ae7f5bdf75671a718d2daf0a64b7885f74510bcd98b1a0bb420eb9a9d0cff"
+ ],
+ "version": "==0.6.0"
+ },
+ "py": {
+ "hashes": [
+ "sha256:8cca5c229d225f8c1e3085be4fcf306090b00850fefad892f9d96c7b6e2f310f",
+ "sha256:ca18943e28235417756316bfada6cd96b23ce60dd532642690dcfdaba988a76d"
+ ],
+ "version": "==1.5.2"
+ },
+ "pytest": {
+ "hashes": [
+ "sha256:95fa025cd6deb5d937e04e368a00552332b58cae23f63b76c8c540ff1733ab6d",
+ "sha256:6074ea3b9c999bd6d0df5fa9d12dd95ccd23550df2a582f5f5b848331d2e82ca"
+ ],
+ "version": "==3.4.0"
+ },
+ "six": {
+ "hashes": [
+ "sha256:832dc0e10feb1aa2c68dcc57dbb658f1c7e65b9b61af69048abc87a2db00a0eb",
+ "sha256:70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9"
+ ],
+ "version": "==1.11.0"
+ }
+ }
+}
diff --git a/uv/spec/fixtures/pipfile_files/malformed_pipfile_source_missing b/uv/spec/fixtures/pipfile_files/malformed_pipfile_source_missing
new file mode 100644
index 00000000000..30ba85fa6ea
--- /dev/null
+++ b/uv/spec/fixtures/pipfile_files/malformed_pipfile_source_missing
@@ -0,0 +1,5 @@
+[dev-packages]
+pytest = "==3.4.0"
+
+[packages]
+requests = "==2.18.0"
diff --git a/uv/spec/fixtures/pipfile_files/malformed_pipfile_source_missing.lock b/uv/spec/fixtures/pipfile_files/malformed_pipfile_source_missing.lock
new file mode 100644
index 00000000000..e3ebcbabbc3
--- /dev/null
+++ b/uv/spec/fixtures/pipfile_files/malformed_pipfile_source_missing.lock
@@ -0,0 +1,88 @@
+{
+ "_meta": {
+ "hash": {
+ "sha256": "60e573c7eb5986a35673614ffd23a685f76846f0ac9f4fa4a4577377e98545a6"
+ },
+ "pipfile-spec": 6,
+ "requires": {},
+ "sources": [
+ {
+ "url": "https://pypi.org/${ENV_VAR}",
+ "verify_ssl": true
+ }
+ ]
+ },
+ "default": {
+ "certifi": {
+ "hashes": [
+ "sha256:14131608ad2fd56836d33a71ee60fa1c82bc9d2c8d98b7bdbc631fe1b3cd1296",
+ "sha256:edbc3f203427eef571f79a7692bb160a2b0f7ccaa31953e99bd17e307cf63f7d"
+ ],
+ "version": "==2018.1.18"
+ },
+ "chardet": {
+ "hashes": [
+ "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691",
+ "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae"
+ ],
+ "version": "==3.0.4"
+ },
+ "idna": {
+ "hashes": [
+ "sha256:cc19709fd6d0cbfed39ea875d29ba6d4e22c0cebc510a76d6302a28385e8bb70",
+ "sha256:3cb5ce08046c4e3a560fc02f138d0ac63e00f8ce5901a56b32ec8b7994082aab"
+ ],
+ "version": "==2.5"
+ },
+ "requests": {
+ "hashes": [
+ "sha256:5e88d64aa56ac0fda54e77fb9762ebc65879e171b746d5479a33c4082519d6c6",
+ "sha256:cd0189f962787284bff715fddaad478eb4d9c15aa167bd64e52ea0f661e7ea5c"
+ ],
+ "version": "==2.18.0"
+ },
+ "urllib3": {
+ "hashes": [
+ "sha256:8ed6d5c1ff9d6ba84677310060d6a3a78ca3072ce0684cb3c645023009c114b1",
+ "sha256:b14486978518ca0901a76ba973d7821047409d7f726f22156b24e83fd71382a5"
+ ],
+ "version": "==1.21.1"
+ }
+ },
+ "develop": {
+ "attrs": {
+ "hashes": [
+ "sha256:a17a9573a6f475c99b551c0e0a812707ddda1ec9653bed04c13841404ed6f450",
+ "sha256:1c7960ccfd6a005cd9f7ba884e6316b5e430a3f1a6c37c5f87d8b43f83b54ec9"
+ ],
+ "version": "==17.4.0"
+ },
+ "pluggy": {
+ "hashes": [
+ "sha256:7f8ae7f5bdf75671a718d2daf0a64b7885f74510bcd98b1a0bb420eb9a9d0cff"
+ ],
+ "version": "==0.6.0"
+ },
+ "py": {
+ "hashes": [
+ "sha256:8cca5c229d225f8c1e3085be4fcf306090b00850fefad892f9d96c7b6e2f310f",
+ "sha256:ca18943e28235417756316bfada6cd96b23ce60dd532642690dcfdaba988a76d"
+ ],
+ "version": "==1.5.2"
+ },
+ "pytest": {
+ "hashes": [
+ "sha256:95fa025cd6deb5d937e04e368a00552332b58cae23f63b76c8c540ff1733ab6d",
+ "sha256:6074ea3b9c999bd6d0df5fa9d12dd95ccd23550df2a582f5f5b848331d2e82ca"
+ ],
+ "version": "==3.4.0"
+ },
+ "six": {
+ "hashes": [
+ "sha256:832dc0e10feb1aa2c68dcc57dbb658f1c7e65b9b61af69048abc87a2db00a0eb",
+ "sha256:70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9"
+ ],
+ "version": "==1.11.0"
+ }
+ }
+}
diff --git a/uv/spec/fixtures/pipfile_files/no_source b/uv/spec/fixtures/pipfile_files/no_source
new file mode 100644
index 00000000000..30ba85fa6ea
--- /dev/null
+++ b/uv/spec/fixtures/pipfile_files/no_source
@@ -0,0 +1,5 @@
+[dev-packages]
+pytest = "==3.4.0"
+
+[packages]
+requests = "==2.18.0"
diff --git a/uv/spec/fixtures/pipfile_files/not_in_lockfile b/uv/spec/fixtures/pipfile_files/not_in_lockfile
new file mode 100644
index 00000000000..b67e707ff83
--- /dev/null
+++ b/uv/spec/fixtures/pipfile_files/not_in_lockfile
@@ -0,0 +1,8 @@
+[[source]]
+name = "pypi"
+url = "https://pypi.org/simple"
+verify_ssl = true
+
+[dev-packages]
+pytest = "*"
+missing = "*"
diff --git a/uv/spec/fixtures/pipfile_files/only_dev b/uv/spec/fixtures/pipfile_files/only_dev
new file mode 100644
index 00000000000..651b5b24d97
--- /dev/null
+++ b/uv/spec/fixtures/pipfile_files/only_dev
@@ -0,0 +1,7 @@
+[[source]]
+name = "pypi"
+url = "https://pypi.org/simple"
+verify_ssl = true
+
+[dev-packages]
+pytest = "*"
diff --git a/uv/spec/fixtures/pipfile_files/only_dev.lock b/uv/spec/fixtures/pipfile_files/only_dev.lock
new file mode 100644
index 00000000000..fbef9b77e79
--- /dev/null
+++ b/uv/spec/fixtures/pipfile_files/only_dev.lock
@@ -0,0 +1,32 @@
+{
+ "_meta": {
+ "hash": {
+ "sha256": "7bc6f4d79c9a73ae9b29d9a3b675f3ee796b8541ec024178bb7c76a61eaac4b1"
+ },
+ "pipfile-spec": 6,
+ "requires": {},
+ "sources": [
+ {
+ "url": "https://pypi.org/simple",
+ "verify_ssl": true
+ }
+ ]
+ },
+ "default": {},
+ "develop": {
+ "py": {
+ "hashes": [
+ "sha256:bf92637198836372b520efcba9e020c330123be8ce527e535d185ed4b6f45694",
+ "sha256:e76826342cefe3c3d5f7e8ee4316b80d1dd8a300781612ddbc765c17ba25a6c6"
+ ],
+ "version": "==1.7.0"
+ },
+ "pytest": {
+ "hashes": [
+ "sha256:27fa6617efc2869d3e969a3e75ec060375bfb28831ade8b5cdd68da3a741dc3c",
+ "sha256:81a25f36a97da3313e1125fce9e7bbbba565bc7fec3c5beb14c262ddab238ac1"
+ ],
+ "version": "==3.2.3"
+ }
+ }
+}
diff --git a/uv/spec/fixtures/pipfile_files/path_dependency b/uv/spec/fixtures/pipfile_files/path_dependency
new file mode 100644
index 00000000000..7ffa1519c75
--- /dev/null
+++ b/uv/spec/fixtures/pipfile_files/path_dependency
@@ -0,0 +1,11 @@
+[[source]]
+name = "pypi"
+url = "https://pypi.org/simple"
+verify_ssl = true
+
+[dev-packages]
+pytest = "==3.4.0"
+
+[packages]
+requests = "==2.18.0"
+"e1839a8" = {path = ".", editable = true, extras=["socks"], version="==0.0.0"}
diff --git a/uv/spec/fixtures/pipfile_files/path_dependency.lock b/uv/spec/fixtures/pipfile_files/path_dependency.lock
new file mode 100644
index 00000000000..918e31fcbe1
--- /dev/null
+++ b/uv/spec/fixtures/pipfile_files/path_dependency.lock
@@ -0,0 +1,81 @@
+{
+ "_meta": {
+ "hash": {
+ "sha256": "1fa9cd2757cc385c836a93a7e9480428b5d00d0f9bddbca159cdff0798c73e05"
+ },
+ "pipfile-spec": 6,
+ "requires": {},
+ "sources": [
+ {
+ "url": "https://pypi.org/simple",
+ "verify_ssl": true
+ }
+ ]
+ },
+ "default": {
+ "contextlib2": {
+ "hashes": [
+ "sha256:509f9419ee91cdd00ba34443217d5ca51f5a364a404e1dce9e8979cea969ca48",
+ "sha256:f5260a6e679d2ff42ec91ec5252f4eeffdcf21053db9113bd0a8e4d953769c00"
+ ],
+ "version": "==0.5.5"
+ },
+ "e1839a8": {
+ "editable": true,
+ "extras": [
+ "socks"
+ ],
+ "path": "."
+ },
+ "raven": {
+ "hashes": [
+ "sha256:13e68bbf21d4d6f0cae4458da5be2d0d538733beabc5f93cb185048b28a77457",
+ "sha256:a06517e9b7858ac41963f9741cc8358005d37511475aaa4c8b692d29ae0a7d94"
+ ],
+ "version": "==5.32.0"
+ },
+ "requests": {
+ "hashes": [
+ "sha256:1cdbed1f0e236f35ef54e919982c7a338e4fea3786310933d3a7887a04b74d75",
+ "sha256:fdb9af60d47ca57a80df0a213336019a34ff6192d8fff361c349f2c8398fe460"
+ ],
+ "version": "==2.6.0"
+ }
+ },
+ "develop": {
+ "attrs": {
+ "hashes": [
+ "sha256:1c7960ccfd6a005cd9f7ba884e6316b5e430a3f1a6c37c5f87d8b43f83b54ec9",
+ "sha256:a17a9573a6f475c99b551c0e0a812707ddda1ec9653bed04c13841404ed6f450"
+ ],
+ "version": "==17.4.0"
+ },
+ "pluggy": {
+ "hashes": [
+ "sha256:7f8ae7f5bdf75671a718d2daf0a64b7885f74510bcd98b1a0bb420eb9a9d0cff"
+ ],
+ "version": "==0.6.0"
+ },
+ "py": {
+ "hashes": [
+ "sha256:29c9fab495d7528e80ba1e343b958684f4ace687327e6f789a94bf3d1915f881",
+ "sha256:983f77f3331356039fdd792e9220b7b8ee1aa6bd2b25f567a963ff1de5a64f6a"
+ ],
+ "version": "==1.5.3"
+ },
+ "pytest": {
+ "hashes": [
+ "sha256:6074ea3b9c999bd6d0df5fa9d12dd95ccd23550df2a582f5f5b848331d2e82ca",
+ "sha256:95fa025cd6deb5d937e04e368a00552332b58cae23f63b76c8c540ff1733ab6d"
+ ],
+ "version": "==3.4.0"
+ },
+ "six": {
+ "hashes": [
+ "sha256:70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9",
+ "sha256:832dc0e10feb1aa2c68dcc57dbb658f1c7e65b9b61af69048abc87a2db00a0eb"
+ ],
+ "version": "==1.11.0"
+ }
+ }
+}
diff --git a/uv/spec/fixtures/pipfile_files/path_dependency_not_self b/uv/spec/fixtures/pipfile_files/path_dependency_not_self
new file mode 100644
index 00000000000..93840f836bc
--- /dev/null
+++ b/uv/spec/fixtures/pipfile_files/path_dependency_not_self
@@ -0,0 +1,11 @@
+[[source]]
+name = "pypi"
+url = "https://pypi.org/simple"
+verify_ssl = true
+
+[dev-packages]
+pytest = "==3.4.0"
+
+[packages]
+requests = "==2.18.0"
+"e1839a8" = {path = "./mydep", editable = true, version = "==0.0.0"}
diff --git a/uv/spec/fixtures/pipfile_files/path_dependency_not_self.lock b/uv/spec/fixtures/pipfile_files/path_dependency_not_self.lock
new file mode 100644
index 00000000000..a3db49b09a2
--- /dev/null
+++ b/uv/spec/fixtures/pipfile_files/path_dependency_not_self.lock
@@ -0,0 +1,109 @@
+{
+ "_meta": {
+ "hash": {
+ "sha256": "ddc6f130206484006653fe65a242e515c22ca1e1f8abbf61fd3e733432cfdda3"
+ },
+ "pipfile-spec": 6,
+ "requires": {},
+ "sources": [
+ {
+ "url": "https://pypi.org/simple",
+ "verify_ssl": true
+ }
+ ]
+ },
+ "default": {
+ "certifi": {
+ "hashes": [
+ "sha256:339dc09518b07e2fa7eda5450740925974815557727d6bd35d319c1524a04a4c",
+ "sha256:6d58c986d22b038c8c0df30d639f23a3e6d172a05c3583e766f4c0b785c0986a"
+ ],
+ "version": "==2018.10.15"
+ },
+ "chardet": {
+ "hashes": [
+ "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae",
+ "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"
+ ],
+ "version": "==3.0.4"
+ },
+ "contextlib2": {
+ "hashes": [
+ "sha256:509f9419ee91cdd00ba34443217d5ca51f5a364a404e1dce9e8979cea969ca48",
+ "sha256:f5260a6e679d2ff42ec91ec5252f4eeffdcf21053db9113bd0a8e4d953769c00"
+ ],
+ "version": "==0.5.5"
+ },
+ "e1839a8": {
+ "editable": true,
+ "path": "./mydep",
+ "version": "==0.0.0"
+ },
+ "idna": {
+ "hashes": [
+ "sha256:3cb5ce08046c4e3a560fc02f138d0ac63e00f8ce5901a56b32ec8b7994082aab",
+ "sha256:cc19709fd6d0cbfed39ea875d29ba6d4e22c0cebc510a76d6302a28385e8bb70"
+ ],
+ "version": "==2.5"
+ },
+ "raven": {
+ "hashes": [
+ "sha256:13e68bbf21d4d6f0cae4458da5be2d0d538733beabc5f93cb185048b28a77457",
+ "sha256:a06517e9b7858ac41963f9741cc8358005d37511475aaa4c8b692d29ae0a7d94"
+ ],
+ "version": "==5.32.0"
+ },
+ "requests": {
+ "hashes": [
+ "sha256:5e88d64aa56ac0fda54e77fb9762ebc65879e171b746d5479a33c4082519d6c6",
+ "sha256:cd0189f962787284bff715fddaad478eb4d9c15aa167bd64e52ea0f661e7ea5c"
+ ],
+ "version": "==2.18.0"
+ },
+ "urllib3": {
+ "hashes": [
+ "sha256:8ed6d5c1ff9d6ba84677310060d6a3a78ca3072ce0684cb3c645023009c114b1",
+ "sha256:b14486978518ca0901a76ba973d7821047409d7f726f22156b24e83fd71382a5"
+ ],
+ "version": "==1.21.1"
+ }
+ },
+ "develop": {
+ "attrs": {
+ "hashes": [
+ "sha256:10cbf6e27dbce8c30807caf056c8eb50917e0eaafe86347671b57254006c3e69",
+ "sha256:ca4be454458f9dec299268d472aaa5a11f67a4ff70093396e1ceae9c76cf4bbb"
+ ],
+ "version": "==18.2.0"
+ },
+ "pluggy": {
+ "hashes": [
+ "sha256:7f8ae7f5bdf75671a718d2daf0a64b7885f74510bcd98b1a0bb420eb9a9d0cff",
+ "sha256:d345c8fe681115900d6da8d048ba67c25df42973bda370783cd58826442dcd7c",
+ "sha256:e160a7fcf25762bb60efc7e171d4497ff1d8d2d75a3d0df7a21b76821ecbf5c5"
+ ],
+ "version": "==0.6.0"
+ },
+ "py": {
+ "hashes": [
+ "sha256:bf92637198836372b520efcba9e020c330123be8ce527e535d185ed4b6f45694",
+ "sha256:e76826342cefe3c3d5f7e8ee4316b80d1dd8a300781612ddbc765c17ba25a6c6"
+ ],
+ "version": "==1.7.0"
+ },
+ "pytest": {
+ "hashes": [
+ "sha256:6074ea3b9c999bd6d0df5fa9d12dd95ccd23550df2a582f5f5b848331d2e82ca",
+ "sha256:95fa025cd6deb5d937e04e368a00552332b58cae23f63b76c8c540ff1733ab6d"
+ ],
+ "version": "==3.4.0"
+ },
+ "six": {
+ "hashes": [
+ "sha256:70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9",
+ "sha256:832dc0e10feb1aa2c68dcc57dbb658f1c7e65b9b61af69048abc87a2db00a0eb"
+ ],
+ "version": "==1.11.0"
+ }
+ }
+}
diff --git a/uv/spec/fixtures/pipfile_files/private_source b/uv/spec/fixtures/pipfile_files/private_source
new file mode 100644
index 00000000000..bd95a2d8ff3
--- /dev/null
+++ b/uv/spec/fixtures/pipfile_files/private_source
@@ -0,0 +1,10 @@
+[[source]]
+name = "internal-pypi"
+url = "https://some.internal.registry.com/pypi/"
+verify_ssl = true
+
+[dev-packages]
+pytest = "==3.4.0"
+
+[packages]
+requests = "==2.18.0"
diff --git a/uv/spec/fixtures/pipfile_files/private_source_auth b/uv/spec/fixtures/pipfile_files/private_source_auth
new file mode 100644
index 00000000000..ae36a45e301
--- /dev/null
+++ b/uv/spec/fixtures/pipfile_files/private_source_auth
@@ -0,0 +1,10 @@
+[[source]]
+name = "internal-pypi"
+url = "https://${ENV_USER}:${ENV_PASSWORD}@pypi.posrip.com/pypi/"
+verify_ssl = true
+
+[dev-packages]
+pytest = "==3.4.0"
+
+[packages]
+requests = "==2.18.0"
diff --git a/uv/spec/fixtures/pipfile_files/problematic_resolution b/uv/spec/fixtures/pipfile_files/problematic_resolution
new file mode 100644
index 00000000000..37d6678f24c
--- /dev/null
+++ b/uv/spec/fixtures/pipfile_files/problematic_resolution
@@ -0,0 +1,16 @@
+[packages]
+twilio = "*"
+
+[dev-packages]
+coverage = "==4.5.1"
+django-nose = "==1.4.5"
+flake8 = "==3.5.0"
+freezegun = "==0.3.10"
+mockredispy = "==2.9.3"
+moto = "==1.3.3"
+pylint = "==1.9.2"
+
+[[source]]
+name = "pypi"
+url = "https://pypi.org/simple/"
+verify_ssl = true
diff --git a/uv/spec/fixtures/pipfile_files/prod_and_dev b/uv/spec/fixtures/pipfile_files/prod_and_dev
new file mode 100644
index 00000000000..651703d5086
--- /dev/null
+++ b/uv/spec/fixtures/pipfile_files/prod_and_dev
@@ -0,0 +1,10 @@
+[[source]]
+name = "pypi"
+url = "https://pypi.org/simple"
+verify_ssl = true
+
+[dev-packages]
+Pytest = "==3.4.0"
+
+[packages]
+Pytest = "==3.4.0"
diff --git a/uv/spec/fixtures/pipfile_files/prod_and_dev.lock b/uv/spec/fixtures/pipfile_files/prod_and_dev.lock
new file mode 100644
index 00000000000..5dcbc70f805
--- /dev/null
+++ b/uv/spec/fixtures/pipfile_files/prod_and_dev.lock
@@ -0,0 +1,91 @@
+{
+ "_meta": {
+ "hash": {
+ "sha256": "32ec8deb339b37ba319dbf315fda41936c1baa7f458a9c74b19e06f4537944f0"
+ },
+ "pipfile-spec": 6,
+ "requires": {},
+ "sources": [
+ {
+ "url": "https://pypi.org/simple",
+ "verify_ssl": true
+ }
+ ]
+ },
+ "default": {
+ "attrs": {
+ "hashes": [
+ "sha256:69c0dbf2ed392de1cb5ec704444b08a5ef81680a61cb899dc08127123af36a79",
+ "sha256:f0b870f674851ecbfbbbd364d6b5cbdff9dcedbc7f3f5e18a6891057f21fe399"
+ ],
+ "version": "==19.1.0"
+ },
+ "pluggy": {
+ "hashes": [
+ "sha256:7f8ae7f5bdf75671a718d2daf0a64b7885f74510bcd98b1a0bb420eb9a9d0cff",
+ "sha256:d345c8fe681115900d6da8d048ba67c25df42973bda370783cd58826442dcd7c",
+ "sha256:e160a7fcf25762bb60efc7e171d4497ff1d8d2d75a3d0df7a21b76821ecbf5c5"
+ ],
+ "version": "==0.6.0"
+ },
+ "py": {
+ "hashes": [
+ "sha256:64f65755aee5b381cea27766a3a147c3f15b9b6b9ac88676de66ba2ae36793fa",
+ "sha256:dc639b046a6e2cff5bbe40194ad65936d6ba360b52b3c3fe1d08a82dd50b5e53"
+ ],
+ "version": "==1.8.0"
+ },
+ "pytest": {
+ "hashes": [
+ "sha256:6074ea3b9c999bd6d0df5fa9d12dd95ccd23550df2a582f5f5b848331d2e82ca",
+ "sha256:95fa025cd6deb5d937e04e368a00552332b58cae23f63b76c8c540ff1733ab6d"
+ ],
+ "version": "==3.4.0"
+ },
+ "six": {
+ "hashes": [
+ "sha256:3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c",
+ "sha256:d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73"
+ ],
+ "version": "==1.12.0"
+ }
+ },
+ "develop": {
+ "attrs": {
+ "hashes": [
+ "sha256:69c0dbf2ed392de1cb5ec704444b08a5ef81680a61cb899dc08127123af36a79",
+ "sha256:f0b870f674851ecbfbbbd364d6b5cbdff9dcedbc7f3f5e18a6891057f21fe399"
+ ],
+ "version": "==19.1.0"
+ },
+ "pluggy": {
+ "hashes": [
+ "sha256:7f8ae7f5bdf75671a718d2daf0a64b7885f74510bcd98b1a0bb420eb9a9d0cff",
+ "sha256:d345c8fe681115900d6da8d048ba67c25df42973bda370783cd58826442dcd7c",
+ "sha256:e160a7fcf25762bb60efc7e171d4497ff1d8d2d75a3d0df7a21b76821ecbf5c5"
+ ],
+ "version": "==0.6.0"
+ },
+ "py": {
+ "hashes": [
+ "sha256:64f65755aee5b381cea27766a3a147c3f15b9b6b9ac88676de66ba2ae36793fa",
+ "sha256:dc639b046a6e2cff5bbe40194ad65936d6ba360b52b3c3fe1d08a82dd50b5e53"
+ ],
+ "version": "==1.8.0"
+ },
+ "pytest": {
+ "hashes": [
+ "sha256:6074ea3b9c999bd6d0df5fa9d12dd95ccd23550df2a582f5f5b848331d2e82ca",
+ "sha256:95fa025cd6deb5d937e04e368a00552332b58cae23f63b76c8c540ff1733ab6d"
+ ],
+ "version": "==3.4.0"
+ },
+ "six": {
+ "hashes": [
+ "sha256:3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c",
+ "sha256:d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73"
+ ],
+ "version": "==1.12.0"
+ }
+ }
+}
diff --git a/uv/spec/fixtures/pipfile_files/prod_and_dev_different b/uv/spec/fixtures/pipfile_files/prod_and_dev_different
new file mode 100644
index 00000000000..893ef34fa65
--- /dev/null
+++ b/uv/spec/fixtures/pipfile_files/prod_and_dev_different
@@ -0,0 +1,10 @@
+[[source]]
+name = "pypi"
+url = "https://pypi.org/simple"
+verify_ssl = true
+
+[dev-packages]
+Pytest = "*"
+
+[packages]
+Pytest = "==3.4.0"
diff --git a/uv/spec/fixtures/pipfile_files/required_python b/uv/spec/fixtures/pipfile_files/required_python
new file mode 100644
index 00000000000..80fdf3f1ebe
--- /dev/null
+++ b/uv/spec/fixtures/pipfile_files/required_python
@@ -0,0 +1,14 @@
+[[source]]
+name = "pypi"
+url = "https://pypi.org/simple"
+verify_ssl = true
+
+[requires]
+python_full_version = "3.9.4"
+python_version = "3.9"
+
+[dev-packages]
+pytest = "==3.4.0"
+
+[packages]
+requests = "==2.18.0"
diff --git a/uv/spec/fixtures/pipfile_files/required_python.lock b/uv/spec/fixtures/pipfile_files/required_python.lock
new file mode 100644
index 00000000000..633a6de2431
--- /dev/null
+++ b/uv/spec/fixtures/pipfile_files/required_python.lock
@@ -0,0 +1,103 @@
+{
+ "_meta": {
+ "hash": {
+ "sha256": "c799e56949184034e6e86e18441504995584b3b1fc9a6511b0aace762dc9206c"
+ },
+ "pipfile-spec": 6,
+ "requires": {
+ "python_full_version": "3.9.4",
+ "python_version": "3.9"
+ },
+ "sources": [
+ {
+ "url": "https://pypi.org/simple",
+ "verify_ssl": true
+ }
+ ]
+ },
+ "default": {
+ "certifi": {
+ "hashes": [
+ "sha256:13e698f54293db9f89122b0581843a782ad0934a4fe0172d2a980ba77fc61bb7",
+ "sha256:9fa520c1bacfb634fa7af20a76bcbd3d5fb390481724c597da32c719a7dca4b0"
+ ],
+ "version": "==2018.4.16"
+ },
+ "chardet": {
+ "hashes": [
+ "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae",
+ "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"
+ ],
+ "version": "==3.0.4"
+ },
+ "idna": {
+ "hashes": [
+ "sha256:3cb5ce08046c4e3a560fc02f138d0ac63e00f8ce5901a56b32ec8b7994082aab",
+ "sha256:cc19709fd6d0cbfed39ea875d29ba6d4e22c0cebc510a76d6302a28385e8bb70"
+ ],
+ "version": "==2.5"
+ },
+ "requests": {
+ "hashes": [
+ "sha256:5e88d64aa56ac0fda54e77fb9762ebc65879e171b746d5479a33c4082519d6c6",
+ "sha256:cd0189f962787284bff715fddaad478eb4d9c15aa167bd64e52ea0f661e7ea5c"
+ ],
+ "index": "pypi",
+ "version": "==2.18.0"
+ },
+ "urllib3": {
+ "hashes": [
+ "sha256:8ed6d5c1ff9d6ba84677310060d6a3a78ca3072ce0684cb3c645023009c114b1",
+ "sha256:b14486978518ca0901a76ba973d7821047409d7f726f22156b24e83fd71382a5"
+ ],
+ "version": "==1.21.1"
+ }
+ },
+ "develop": {
+ "attrs": {
+ "hashes": [
+ "sha256:4b90b09eeeb9b88c35bc642cbac057e45a5fd85367b985bd2809c62b7b939265",
+ "sha256:e0d0eb91441a3b53dab4d9b743eafc1ac44476296a2053b6ca3af0b139faf87b"
+ ],
+ "version": "==18.1.0"
+ },
+ "funcsigs": {
+ "hashes": [
+ "sha256:330cc27ccbf7f1e992e69fef78261dc7c6569012cf397db8d3de0234e6c937ca",
+ "sha256:a7bb0f2cf3a3fd1ab2732cb49eba4252c2af4240442415b4abce3b87022a8f50"
+ ],
+ "markers": "python_version < '3.0'",
+ "version": "==1.0.2"
+ },
+ "pluggy": {
+ "hashes": [
+ "sha256:7f8ae7f5bdf75671a718d2daf0a64b7885f74510bcd98b1a0bb420eb9a9d0cff",
+ "sha256:d345c8fe681115900d6da8d048ba67c25df42973bda370783cd58826442dcd7c",
+ "sha256:e160a7fcf25762bb60efc7e171d4497ff1d8d2d75a3d0df7a21b76821ecbf5c5"
+ ],
+ "version": "==0.6.0"
+ },
+ "py": {
+ "hashes": [
+ "sha256:29c9fab495d7528e80ba1e343b958684f4ace687327e6f789a94bf3d1915f881",
+ "sha256:983f77f3331356039fdd792e9220b7b8ee1aa6bd2b25f567a963ff1de5a64f6a"
+ ],
+ "version": "==1.5.3"
+ },
+ "pytest": {
+ "hashes": [
+ "sha256:6074ea3b9c999bd6d0df5fa9d12dd95ccd23550df2a582f5f5b848331d2e82ca",
+ "sha256:95fa025cd6deb5d937e04e368a00552332b58cae23f63b76c8c540ff1733ab6d"
+ ],
+ "index": "pypi",
+ "version": "==3.4.0"
+ },
+ "six": {
+ "hashes": [
+ "sha256:70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9",
+ "sha256:832dc0e10feb1aa2c68dcc57dbb658f1c7e65b9b61af69048abc87a2db00a0eb"
+ ],
+ "version": "==1.11.0"
+ }
+ }
+}
diff --git a/uv/spec/fixtures/pipfile_files/required_python_implicit b/uv/spec/fixtures/pipfile_files/required_python_implicit
new file mode 100644
index 00000000000..e02788e7517
--- /dev/null
+++ b/uv/spec/fixtures/pipfile_files/required_python_implicit
@@ -0,0 +1,10 @@
+[[source]]
+name = "pypi"
+url = "https://pypi.org/simple"
+verify_ssl = true
+
+[dev-packages]
+pytest = "==3.4.0"
+
+[packages]
+futures = "==3.2.0"
diff --git a/uv/spec/fixtures/pipfile_files/required_python_implicit.lock b/uv/spec/fixtures/pipfile_files/required_python_implicit.lock
new file mode 100644
index 00000000000..34c3793c163
--- /dev/null
+++ b/uv/spec/fixtures/pipfile_files/required_python_implicit.lock
@@ -0,0 +1,72 @@
+{
+ "_meta": {
+ "hash": {
+ "sha256": "052031f27a806ca65a0f6c8298c89578ff9e86161d6cea2442f5bf7cc4b64438"
+ },
+ "pipfile-spec": 6,
+ "requires": {},
+ "sources": [
+ {
+ "url": "https://pypi.org/simple",
+ "verify_ssl": true
+ }
+ ]
+ },
+ "default": {
+ "futures": {
+ "hashes": [
+ "sha256:9ec02aa7d674acb8618afb127e27fde7fc68994c0437ad759fa094a574adb265",
+ "sha256:ec0a6cb848cc212002b9828c3e34c675e0c9ff6741dc445cab6fdd4e1085d1f1"
+ ],
+ "index": "pypi",
+ "version": "==3.2.0"
+ }
+ },
+ "develop": {
+ "attrs": {
+ "hashes": [
+ "sha256:10cbf6e27dbce8c30807caf056c8eb50917e0eaafe86347671b57254006c3e69",
+ "sha256:ca4be454458f9dec299268d472aaa5a11f67a4ff70093396e1ceae9c76cf4bbb"
+ ],
+ "version": "==18.2.0"
+ },
+ "funcsigs": {
+ "hashes": [
+ "sha256:330cc27ccbf7f1e992e69fef78261dc7c6569012cf397db8d3de0234e6c937ca",
+ "sha256:a7bb0f2cf3a3fd1ab2732cb49eba4252c2af4240442415b4abce3b87022a8f50"
+ ],
+ "markers": "python_version < '3.0'",
+ "version": "==1.0.2"
+ },
+ "pluggy": {
+ "hashes": [
+ "sha256:7f8ae7f5bdf75671a718d2daf0a64b7885f74510bcd98b1a0bb420eb9a9d0cff",
+ "sha256:d345c8fe681115900d6da8d048ba67c25df42973bda370783cd58826442dcd7c",
+ "sha256:e160a7fcf25762bb60efc7e171d4497ff1d8d2d75a3d0df7a21b76821ecbf5c5"
+ ],
+ "version": "==0.6.0"
+ },
+ "py": {
+ "hashes": [
+ "sha256:64f65755aee5b381cea27766a3a147c3f15b9b6b9ac88676de66ba2ae36793fa",
+ "sha256:dc639b046a6e2cff5bbe40194ad65936d6ba360b52b3c3fe1d08a82dd50b5e53"
+ ],
+ "version": "==1.8.0"
+ },
+ "pytest": {
+ "hashes": [
+ "sha256:6074ea3b9c999bd6d0df5fa9d12dd95ccd23550df2a582f5f5b848331d2e82ca",
+ "sha256:95fa025cd6deb5d937e04e368a00552332b58cae23f63b76c8c540ff1733ab6d"
+ ],
+ "index": "pypi",
+ "version": "==3.4.0"
+ },
+ "six": {
+ "hashes": [
+ "sha256:3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c",
+ "sha256:d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73"
+ ],
+ "version": "==1.12.0"
+ }
+ }
+}
diff --git a/uv/spec/fixtures/pipfile_files/required_python_invalid b/uv/spec/fixtures/pipfile_files/required_python_invalid
new file mode 100644
index 00000000000..44c43aba04f
--- /dev/null
+++ b/uv/spec/fixtures/pipfile_files/required_python_invalid
@@ -0,0 +1,13 @@
+[[source]]
+name = "pypi"
+url = "https://pypi.org/simple"
+verify_ssl = true
+
+[requires]
+python_version = ">=3.5"
+
+[dev-packages]
+pytest = "==3.4.0"
+
+[packages]
+requests = "==2.18.0"
diff --git a/uv/spec/fixtures/pipfile_files/required_python_unsupported b/uv/spec/fixtures/pipfile_files/required_python_unsupported
new file mode 100644
index 00000000000..f957d73a448
--- /dev/null
+++ b/uv/spec/fixtures/pipfile_files/required_python_unsupported
@@ -0,0 +1,13 @@
+[[source]]
+name = "pypi"
+url = "https://pypi.org/simple"
+verify_ssl = true
+
+[requires]
+python_version = "3.4"
+
+[dev-packages]
+pytest = "==3.4.0"
+
+[packages]
+requests = "==2.18.0"
diff --git a/uv/spec/fixtures/pipfile_files/star b/uv/spec/fixtures/pipfile_files/star
new file mode 100644
index 00000000000..4f40d887bfd
--- /dev/null
+++ b/uv/spec/fixtures/pipfile_files/star
@@ -0,0 +1,9 @@
+[[source]]
+url = "https://pypi.org/simple"
+verify_ssl = true
+name = "pypi"
+
+[packages]
+boto3 = "*"
+
+[dev-packages]
diff --git a/uv/spec/fixtures/pipfile_files/star.lock b/uv/spec/fixtures/pipfile_files/star.lock
new file mode 100644
index 00000000000..89cf6f864e5
--- /dev/null
+++ b/uv/spec/fixtures/pipfile_files/star.lock
@@ -0,0 +1,76 @@
+{
+ "_meta": {
+ "hash": {
+ "sha256": "cfb5aacb7331c912125612597b3b297fc2103296077590290adf9609764d0d46"
+ },
+ "pipfile-spec": 6,
+ "requires": {},
+ "sources": [
+ {
+ "name": "pypi",
+ "url": "https://pypi.org/simple",
+ "verify_ssl": true
+ }
+ ]
+ },
+ "default": {
+ "boto3": {
+ "hashes": [
+ "sha256:33062ab3801029ab7b2cb35b6bf4768715d13c5f9ea7d5dce22ace6219c1dc7a",
+ "sha256:cda98a2952cccb1db4208c53a1bba6585620fffa0ca05244827ca65884856d1f"
+ ],
+ "index": "pypi",
+ "markers": "python_version >= '3.7'",
+ "version": "==1.28.50"
+ },
+ "botocore": {
+ "hashes": [
+ "sha256:b8f35d65f2b45af50c36fc25cc1844d6bd61d38d2148b2ef133b8f10e198555d",
+ "sha256:ce58e688222df73ec5691f934be1a2122a52c9d11d3037b586b3fff16ed6d25f"
+ ],
+ "markers": "python_version >= '3.7'",
+ "version": "==1.31.85"
+ },
+ "jmespath": {
+ "hashes": [
+ "sha256:02e2e4cc71b5bcab88332eebf907519190dd9e6e82107fa7f83b1003a6252980",
+ "sha256:90261b206d6defd58fdd5e85f478bf633a2901798906be2ad389150c5c60edbe"
+ ],
+ "markers": "python_version >= '3.7'",
+ "version": "==1.0.1"
+ },
+ "python-dateutil": {
+ "hashes": [
+ "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86",
+ "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"
+ ],
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
+ "version": "==2.8.2"
+ },
+ "s3transfer": {
+ "hashes": [
+ "sha256:b014be3a8a2aab98cfe1abc7229cc5a9a0cf05eb9c1f2b86b230fd8df3f78084",
+ "sha256:cab66d3380cca3e70939ef2255d01cd8aece6a4907a9528740f668c4b0611861"
+ ],
+ "markers": "python_version >= '3.7'",
+ "version": "==0.6.2"
+ },
+ "six": {
+ "hashes": [
+ "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926",
+ "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"
+ ],
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
+ "version": "==1.16.0"
+ },
+ "urllib3": {
+ "hashes": [
+ "sha256:c97dfde1f7bd43a71c8d2a58e369e9b2bf692d1334ea9f9cae55add7d0dd0f84",
+ "sha256:fdb6d215c776278489906c2f8916e6e7d4f5a9b602ccbcfdf7f016fc8da0596e"
+ ],
+ "markers": "python_version >= '3.10'",
+ "version": "==2.0.7"
+ }
+ },
+ "develop": {}
+}
diff --git a/uv/spec/fixtures/pipfile_files/unnecessary_subdependency.lock b/uv/spec/fixtures/pipfile_files/unnecessary_subdependency.lock
new file mode 100644
index 00000000000..bcec89b3015
--- /dev/null
+++ b/uv/spec/fixtures/pipfile_files/unnecessary_subdependency.lock
@@ -0,0 +1,103 @@
+{
+ "_meta": {
+ "hash": {
+ "sha256": "40d0c95e8f178554fbb42aee3b2e2dee2241acccb5974362f806958d273f53d1"
+ },
+ "pipfile-spec": 6,
+ "requires": {},
+ "sources": [
+ {
+ "url": "https://pypi.org/simple",
+ "verify_ssl": true
+ }
+ ]
+ },
+ "default": {
+ "certifi": {
+ "hashes": [
+ "sha256:13e698f54293db9f89122b0581843a782ad0934a4fe0172d2a980ba77fc61bb7",
+ "sha256:9fa520c1bacfb634fa7af20a76bcbd3d5fb390481724c597da32c719a7dca4b0"
+ ],
+ "version": "==2018.4.16"
+ },
+ "chardet": {
+ "hashes": [
+ "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae",
+ "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"
+ ],
+ "version": "==3.0.4"
+ },
+ "idna": {
+ "hashes": [
+ "sha256:3cb5ce08046c4e3a560fc02f138d0ac63e00f8ce5901a56b32ec8b7994082aab",
+ "sha256:cc19709fd6d0cbfed39ea875d29ba6d4e22c0cebc510a76d6302a28385e8bb70"
+ ],
+ "version": "==2.5"
+ },
+ "requests": {
+ "hashes": [
+ "sha256:5e88d64aa56ac0fda54e77fb9762ebc65879e171b746d5479a33c4082519d6c6",
+ "sha256:cd0189f962787284bff715fddaad478eb4d9c15aa167bd64e52ea0f661e7ea5c"
+ ],
+ "index": "pypi",
+ "version": "==2.18.0"
+ },
+ "urllib3": {
+ "hashes": [
+ "sha256:8ed6d5c1ff9d6ba84677310060d6a3a78ca3072ce0684cb3c645023009c114b1",
+ "sha256:b14486978518ca0901a76ba973d7821047409d7f726f22156b24e83fd71382a5"
+ ],
+ "version": "==1.21.1"
+ }
+ },
+ "develop": {
+ "attrs": {
+ "hashes": [
+ "sha256:4b90b09eeeb9b88c35bc642cbac057e45a5fd85367b985bd2809c62b7b939265",
+ "sha256:e0d0eb91441a3b53dab4d9b743eafc1ac44476296a2053b6ca3af0b139faf87b"
+ ],
+ "version": "==18.1.0"
+ },
+ "funcsigs": {
+ "hashes": [
+ "sha256:330cc27ccbf7f1e992e69fef78261dc7c6569012cf397db8d3de0234e6c937ca",
+ "sha256:a7bb0f2cf3a3fd1ab2732cb49eba4252c2af4240442415b4abce3b87022a8f50"
+ ],
+ "markers": "python_version < '3.0'",
+ "version": "==1.0.2"
+ },
+ "pluggy": {
+ "hashes": [
+ "sha256:7f8ae7f5bdf75671a718d2daf0a64b7885f74510bcd98b1a0bb420eb9a9d0cff",
+ "sha256:d345c8fe681115900d6da8d048ba67c25df42973bda370783cd58826442dcd7c",
+ "sha256:e160a7fcf25762bb60efc7e171d4497ff1d8d2d75a3d0df7a21b76821ecbf5c5"
+ ],
+ "version": "==0.6.0"
+ },
+ "py": {
+ "hashes": [
+ "sha256:29c9fab495d7528e80ba1e343b958684f4ace687327e6f789a94bf3d1915f881",
+ "sha256:983f77f3331356039fdd792e9220b7b8ee1aa6bd2b25f567a963ff1de5a64f6a"
+ ],
+ "version": "==1.5.3"
+ },
+ "pytest": {
+ "hashes": [
+ "sha256:6074ea3b9c999bd6d0df5fa9d12dd95ccd23550df2a582f5f5b848331d2e82ca",
+ "sha256:95fa025cd6deb5d937e04e368a00552332b58cae23f63b76c8c540ff1733ab6d"
+ ],
+ "index": "pypi",
+ "version": "==3.4.0"
+ },
+ "setuptools": {
+ "version": "==40.2.0"
+ },
+ "six": {
+ "hashes": [
+ "sha256:70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9",
+ "sha256:832dc0e10feb1aa2c68dcc57dbb658f1c7e65b9b61af69048abc87a2db00a0eb"
+ ],
+ "version": "==1.11.0"
+ }
+ }
+}
diff --git a/uv/spec/fixtures/pipfile_files/unparseable b/uv/spec/fixtures/pipfile_files/unparseable
new file mode 100644
index 00000000000..cd5b790b1ad
--- /dev/null
+++ b/uv/spec/fixtures/pipfile_files/unparseable
@@ -0,0 +1,14 @@
+[[source]]
+name = "pypi"
+url = "https://pypi.org/simple"
+verify_ssl = true
+
+[dev-packages]
+
+[requires]
+python_version = "3.7"
+
+[packages]
+
+numpy = "*"
+geckoboard.py ">=1.0.0, <2.0"
diff --git a/uv/spec/fixtures/pipfile_files/unparseable.lock b/uv/spec/fixtures/pipfile_files/unparseable.lock
new file mode 100644
index 00000000000..1d36fee78a4
--- /dev/null
+++ b/uv/spec/fixtures/pipfile_files/unparseable.lock
@@ -0,0 +1,99 @@
+ "_meta": {
+ "hash": {
+ "sha256": "40d0c95e8f178554fbb42aee3b2e2dee2241acccb5974362f806958d273f53d1"
+ },
+ "pipfile-spec": 6,
+ "requires": {},
+ "sources": [
+ {
+ "url": "https://pypi.org/simple",
+ "verify_ssl": true
+ }
+ ]
+ },
+ "default": {
+ "certifi": {
+ "hashes": [
+ "sha256:13e698f54293db9f89122b0581843a782ad0934a4fe0172d2a980ba77fc61bb7",
+ "sha256:9fa520c1bacfb634fa7af20a76bcbd3d5fb390481724c597da32c719a7dca4b0"
+ ],
+ "version": "==2018.4.16"
+ },
+ "chardet": {
+ "hashes": [
+ "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae",
+ "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"
+ ],
+ "version": "==3.0.4"
+ },
+ "idna": {
+ "hashes": [
+ "sha256:3cb5ce08046c4e3a560fc02f138d0ac63e00f8ce5901a56b32ec8b7994082aab",
+ "sha256:cc19709fd6d0cbfed39ea875d29ba6d4e22c0cebc510a76d6302a28385e8bb70"
+ ],
+ "version": "==2.5"
+ },
+ "requests": {
+ "hashes": [
+ "sha256:5e88d64aa56ac0fda54e77fb9762ebc65879e171b746d5479a33c4082519d6c6",
+ "sha256:cd0189f962787284bff715fddaad478eb4d9c15aa167bd64e52ea0f661e7ea5c"
+ ],
+ "index": "pypi",
+ "version": "==2.18.0"
+ },
+ "urllib3": {
+ "hashes": [
+ "sha256:8ed6d5c1ff9d6ba84677310060d6a3a78ca3072ce0684cb3c645023009c114b1",
+ "sha256:b14486978518ca0901a76ba973d7821047409d7f726f22156b24e83fd71382a5"
+ ],
+ "version": "==1.21.1"
+ }
+ },
+ "develop": {
+ "attrs": {
+ "hashes": [
+ "sha256:4b90b09eeeb9b88c35bc642cbac057e45a5fd85367b985bd2809c62b7b939265",
+ "sha256:e0d0eb91441a3b53dab4d9b743eafc1ac44476296a2053b6ca3af0b139faf87b"
+ ],
+ "version": "==18.1.0"
+ },
+ "funcsigs": {
+ "hashes": [
+ "sha256:330cc27ccbf7f1e992e69fef78261dc7c6569012cf397db8d3de0234e6c937ca",
+ "sha256:a7bb0f2cf3a3fd1ab2732cb49eba4252c2af4240442415b4abce3b87022a8f50"
+ ],
+ "markers": "python_version < '3.0'",
+ "version": "==1.0.2"
+ },
+ "pluggy": {
+ "hashes": [
+ "sha256:7f8ae7f5bdf75671a718d2daf0a64b7885f74510bcd98b1a0bb420eb9a9d0cff",
+ "sha256:d345c8fe681115900d6da8d048ba67c25df42973bda370783cd58826442dcd7c",
+ "sha256:e160a7fcf25762bb60efc7e171d4497ff1d8d2d75a3d0df7a21b76821ecbf5c5"
+ ],
+ "version": "==0.6.0"
+ },
+ "py": {
+ "hashes": [
+ "sha256:29c9fab495d7528e80ba1e343b958684f4ace687327e6f789a94bf3d1915f881",
+ "sha256:983f77f3331356039fdd792e9220b7b8ee1aa6bd2b25f567a963ff1de5a64f6a"
+ ],
+ "version": "==1.5.3"
+ },
+ "pytest": {
+ "hashes": [
+ "sha256:6074ea3b9c999bd6d0df5fa9d12dd95ccd23550df2a582f5f5b848331d2e82ca",
+ "sha256:95fa025cd6deb5d937e04e368a00552332b58cae23f63b76c8c540ff1733ab6d"
+ ],
+ "index": "pypi",
+ "version": "==3.4.0"
+ },
+ "six": {
+ "hashes": [
+ "sha256:70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9",
+ "sha256:832dc0e10feb1aa2c68dcc57dbb658f1c7e65b9b61af69048abc87a2db00a0eb"
+ ],
+ "version": "==1.11.0"
+ }
+ }
+}
diff --git a/uv/spec/fixtures/pipfile_files/version_hash b/uv/spec/fixtures/pipfile_files/version_hash
new file mode 100644
index 00000000000..6514e4a2e9f
--- /dev/null
+++ b/uv/spec/fixtures/pipfile_files/version_hash
@@ -0,0 +1,10 @@
+[[source]]
+name = "pypi"
+url = "https://pypi.org/simple"
+verify_ssl = true
+
+[dev-packages]
+pytest = "==3.4.0"
+
+[packages]
+requests = { version = "==2.18.0" }
diff --git a/uv/spec/fixtures/pipfile_files/version_hash.lock b/uv/spec/fixtures/pipfile_files/version_hash.lock
new file mode 100644
index 00000000000..715e658561f
--- /dev/null
+++ b/uv/spec/fixtures/pipfile_files/version_hash.lock
@@ -0,0 +1,88 @@
+{
+ "_meta": {
+ "hash": {
+ "sha256": "53fe2c356a1edfc7e1f5281b4f86c8f08ed9050eecf621217d5d40282ca21ace"
+ },
+ "pipfile-spec": 6,
+ "requires": {},
+ "sources": [
+ {
+ "url": "https://pypi.org/simple",
+ "verify_ssl": true
+ }
+ ]
+ },
+ "default": {
+ "certifi": {
+ "hashes": [
+ "sha256:14131608ad2fd56836d33a71ee60fa1c82bc9d2c8d98b7bdbc631fe1b3cd1296",
+ "sha256:edbc3f203427eef571f79a7692bb160a2b0f7ccaa31953e99bd17e307cf63f7d"
+ ],
+ "version": "==2018.1.18"
+ },
+ "chardet": {
+ "hashes": [
+ "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691",
+ "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae"
+ ],
+ "version": "==3.0.4"
+ },
+ "idna": {
+ "hashes": [
+ "sha256:cc19709fd6d0cbfed39ea875d29ba6d4e22c0cebc510a76d6302a28385e8bb70",
+ "sha256:3cb5ce08046c4e3a560fc02f138d0ac63e00f8ce5901a56b32ec8b7994082aab"
+ ],
+ "version": "==2.5"
+ },
+ "requests": {
+ "hashes": [
+ "sha256:5e88d64aa56ac0fda54e77fb9762ebc65879e171b746d5479a33c4082519d6c6",
+ "sha256:cd0189f962787284bff715fddaad478eb4d9c15aa167bd64e52ea0f661e7ea5c"
+ ],
+ "version": "==2.18.0"
+ },
+ "urllib3": {
+ "hashes": [
+ "sha256:8ed6d5c1ff9d6ba84677310060d6a3a78ca3072ce0684cb3c645023009c114b1",
+ "sha256:b14486978518ca0901a76ba973d7821047409d7f726f22156b24e83fd71382a5"
+ ],
+ "version": "==1.21.1"
+ }
+ },
+ "develop": {
+ "attrs": {
+ "hashes": [
+ "sha256:a17a9573a6f475c99b551c0e0a812707ddda1ec9653bed04c13841404ed6f450",
+ "sha256:1c7960ccfd6a005cd9f7ba884e6316b5e430a3f1a6c37c5f87d8b43f83b54ec9"
+ ],
+ "version": "==17.4.0"
+ },
+ "pluggy": {
+ "hashes": [
+ "sha256:7f8ae7f5bdf75671a718d2daf0a64b7885f74510bcd98b1a0bb420eb9a9d0cff"
+ ],
+ "version": "==0.6.0"
+ },
+ "py": {
+ "hashes": [
+ "sha256:8cca5c229d225f8c1e3085be4fcf306090b00850fefad892f9d96c7b6e2f310f",
+ "sha256:ca18943e28235417756316bfada6cd96b23ce60dd532642690dcfdaba988a76d"
+ ],
+ "version": "==1.5.2"
+ },
+ "pytest": {
+ "hashes": [
+ "sha256:95fa025cd6deb5d937e04e368a00552332b58cae23f63b76c8c540ff1733ab6d",
+ "sha256:6074ea3b9c999bd6d0df5fa9d12dd95ccd23550df2a582f5f5b848331d2e82ca"
+ ],
+ "version": "==3.4.0"
+ },
+ "six": {
+ "hashes": [
+ "sha256:832dc0e10feb1aa2c68dcc57dbb658f1c7e65b9b61af69048abc87a2db00a0eb",
+ "sha256:70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9"
+ ],
+ "version": "==1.11.0"
+ }
+ }
+}
diff --git a/uv/spec/fixtures/pipfile_files/version_not_specified b/uv/spec/fixtures/pipfile_files/version_not_specified
new file mode 100644
index 00000000000..6cb20258d45
--- /dev/null
+++ b/uv/spec/fixtures/pipfile_files/version_not_specified
@@ -0,0 +1,10 @@
+[[source]]
+name = "pypi"
+url = "https://pypi.org/simple"
+verify_ssl = true
+
+[dev-packages]
+pytest = "*"
+
+[packages]
+requests = "*"
diff --git a/uv/spec/fixtures/pipfile_files/version_not_specified.lock b/uv/spec/fixtures/pipfile_files/version_not_specified.lock
new file mode 100644
index 00000000000..35c73b8e759
--- /dev/null
+++ b/uv/spec/fixtures/pipfile_files/version_not_specified.lock
@@ -0,0 +1,69 @@
+{
+ "_meta": {
+ "hash": {
+ "sha256": "e76ae491d793d659f05c7f7eab261fd6167dc062efcba08f17be68e73eb87665"
+ },
+ "pipfile-spec": 6,
+ "requires": {},
+ "sources": [
+ {
+ "name": "pypi",
+ "url": "https://pypi.org/simple",
+ "verify_ssl": true
+ }
+ ]
+ },
+ "default": {
+ "certifi": {
+ "hashes": [
+ "sha256:244be0d93b71e93fc0a0a479862051414d0e00e16435707e5bf5000f92e04694",
+ "sha256:5ec74291ca1136b40f0379e1128ff80e866597e4e2c1e755739a913bbc3613c0"
+ ],
+ "version": "==2017.11.5"
+ },
+ "chardet": {
+ "hashes": [
+ "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691",
+ "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae"
+ ],
+ "version": "==3.0.4"
+ },
+ "idna": {
+ "hashes": [
+ "sha256:cc19709fd6d0cbfed39ea875d29ba6d4e22c0cebc510a76d6302a28385e8bb70",
+ "sha256:3cb5ce08046c4e3a560fc02f138d0ac63e00f8ce5901a56b32ec8b7994082aab"
+ ],
+ "version": "==2.5"
+ },
+ "requests": {
+ "hashes": [
+ "sha256:5e88d64aa56ac0fda54e77fb9762ebc65879e171b746d5479a33c4082519d6c6",
+ "sha256:cd0189f962787284bff715fddaad478eb4d9c15aa167bd64e52ea0f661e7ea5c"
+ ],
+ "version": "==2.18.0"
+ },
+ "urllib3": {
+ "hashes": [
+ "sha256:8ed6d5c1ff9d6ba84677310060d6a3a78ca3072ce0684cb3c645023009c114b1",
+ "sha256:b14486978518ca0901a76ba973d7821047409d7f726f22156b24e83fd71382a5"
+ ],
+ "version": "==1.21.1"
+ }
+ },
+ "develop": {
+ "py": {
+ "hashes": [
+ "sha256:8cca5c229d225f8c1e3085be4fcf306090b00850fefad892f9d96c7b6e2f310f",
+ "sha256:ca18943e28235417756316bfada6cd96b23ce60dd532642690dcfdaba988a76d"
+ ],
+ "version": "==1.5.2"
+ },
+ "pytest": {
+ "hashes": [
+ "sha256:81a25f36a97da3313e1125fce9e7bbbba565bc7fec3c5beb14c262ddab238ac1",
+ "sha256:27fa6617efc2869d3e969a3e75ec060375bfb28831ade8b5cdd68da3a741dc3c"
+ ],
+ "version": "==3.2.3"
+ }
+ }
+}
diff --git a/uv/spec/fixtures/pipfile_files/version_table b/uv/spec/fixtures/pipfile_files/version_table
new file mode 100644
index 00000000000..f72cea8958c
--- /dev/null
+++ b/uv/spec/fixtures/pipfile_files/version_table
@@ -0,0 +1,12 @@
+[[source]]
+name = "pypi"
+url = "https://pypi.org/simple"
+verify_ssl = true
+
+[dev-packages]
+pytest = "==3.4.0"
+
+[packages.requests]
+
+version = "==2.18.0"
+markers = "python_version < '3.5'"
diff --git a/uv/spec/fixtures/pipfile_files/wildcard b/uv/spec/fixtures/pipfile_files/wildcard
new file mode 100644
index 00000000000..2cde9a7cdfe
--- /dev/null
+++ b/uv/spec/fixtures/pipfile_files/wildcard
@@ -0,0 +1,10 @@
+[[source]]
+name = "pypi"
+url = "https://pypi.org/simple"
+verify_ssl = true
+
+[dev-packages]
+Pytest = "==3.4.*"
+
+[packages]
+Requests = "==2.18.*"
diff --git a/uv/spec/fixtures/pipfile_files/with_quotes b/uv/spec/fixtures/pipfile_files/with_quotes
new file mode 100644
index 00000000000..89ea1a02240
--- /dev/null
+++ b/uv/spec/fixtures/pipfile_files/with_quotes
@@ -0,0 +1,13 @@
+[[source]]
+name = "pypi"
+url = "https://pypi.org/simple"
+verify_ssl = true
+
+[dev-packages]
+pytest = "==3.2.3"
+extension-pytest = "==3.2.3"
+pytest-extension = "==3.2.3"
+
+[packages]
+"requests" = "==2.18.0"
+'python_decouple' = "==3.1"
diff --git a/uv/spec/fixtures/pipfile_files/yanked b/uv/spec/fixtures/pipfile_files/yanked
new file mode 100644
index 00000000000..fcd8009680a
--- /dev/null
+++ b/uv/spec/fixtures/pipfile_files/yanked
@@ -0,0 +1,10 @@
+[[source]]
+name = "pypi"
+url = "https://pypi.org/simple"
+verify_ssl = true
+
+[dev-packages]
+Pytest = "==10.4.0"
+
+[packages]
+Requests = "==2.18.0"
diff --git a/uv/spec/fixtures/pipfile_files/yanked.lock b/uv/spec/fixtures/pipfile_files/yanked.lock
new file mode 100644
index 00000000000..69b052acff5
--- /dev/null
+++ b/uv/spec/fixtures/pipfile_files/yanked.lock
@@ -0,0 +1,100 @@
+{
+ "_meta": {
+ "hash": {
+ "sha256": "40d0c95e8f178554fbb42aee3b2e2dee2241acccb5974362f806958d273f53d1"
+ },
+ "pipfile-spec": 6,
+ "requires": {},
+ "sources": [
+ {
+ "url": "https://pypi.org/simple",
+ "verify_ssl": true
+ }
+ ]
+ },
+ "default": {
+ "certifi": {
+ "hashes": [
+ "sha256:13e698f54293db9f89122b0581843a782ad0934a4fe0172d2a980ba77fc61bb7",
+ "sha256:9fa520c1bacfb634fa7af20a76bcbd3d5fb390481724c597da32c719a7dca4b0"
+ ],
+ "version": "==2018.4.16"
+ },
+ "chardet": {
+ "hashes": [
+ "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae",
+ "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"
+ ],
+ "version": "==3.0.4"
+ },
+ "idna": {
+ "hashes": [
+ "sha256:3cb5ce08046c4e3a560fc02f138d0ac63e00f8ce5901a56b32ec8b7994082aab",
+ "sha256:cc19709fd6d0cbfed39ea875d29ba6d4e22c0cebc510a76d6302a28385e8bb70"
+ ],
+ "version": "==2.5"
+ },
+ "requests": {
+ "hashes": [
+ "sha256:5e88d64aa56ac0fda54e77fb9762ebc65879e171b746d5479a33c4082519d6c6",
+ "sha256:cd0189f962787284bff715fddaad478eb4d9c15aa167bd64e52ea0f661e7ea5c"
+ ],
+ "index": "pypi",
+ "version": "==2.18.0"
+ },
+ "urllib3": {
+ "hashes": [
+ "sha256:8ed6d5c1ff9d6ba84677310060d6a3a78ca3072ce0684cb3c645023009c114b1",
+ "sha256:b14486978518ca0901a76ba973d7821047409d7f726f22156b24e83fd71382a5"
+ ],
+ "version": "==1.21.1"
+ }
+ },
+ "develop": {
+ "attrs": {
+ "hashes": [
+ "sha256:4b90b09eeeb9b88c35bc642cbac057e45a5fd85367b985bd2809c62b7b939265",
+ "sha256:e0d0eb91441a3b53dab4d9b743eafc1ac44476296a2053b6ca3af0b139faf87b"
+ ],
+ "version": "==18.1.0"
+ },
+ "funcsigs": {
+ "hashes": [
+ "sha256:330cc27ccbf7f1e992e69fef78261dc7c6569012cf397db8d3de0234e6c937ca",
+ "sha256:a7bb0f2cf3a3fd1ab2732cb49eba4252c2af4240442415b4abce3b87022a8f50"
+ ],
+ "markers": "python_version < '3.0'",
+ "version": "==1.0.2"
+ },
+ "pluggy": {
+ "hashes": [
+ "sha256:7f8ae7f5bdf75671a718d2daf0a64b7885f74510bcd98b1a0bb420eb9a9d0cff",
+ "sha256:d345c8fe681115900d6da8d048ba67c25df42973bda370783cd58826442dcd7c",
+ "sha256:e160a7fcf25762bb60efc7e171d4497ff1d8d2d75a3d0df7a21b76821ecbf5c5"
+ ],
+ "version": "==0.6.0"
+ },
+ "py": {
+ "hashes": [
+ "sha256:29c9fab495d7528e80ba1e343b958684f4ace687327e6f789a94bf3d1915f881",
+ "sha256:983f77f3331356039fdd792e9220b7b8ee1aa6bd2b25f567a963ff1de5a64f6a"
+ ],
+ "version": "==1.5.3"
+ },
+ "pytest": {
+ "hashes": [
+ "sha256:3074ea3b9c999bd6d0df5fa9d12dd95ccd23550df2a582f5f5b848331d2e82ca",
+ "sha256:35fa025cd6deb5d937e04e368a00552332b58cae23f63b76c8c540ff1733ab6d"
+ ],
+ "index": "pypi",
+ "version": "==10.4.0"
+ },
+ "six": {
+ "hashes": [
+ "sha256:70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9",
+ "sha256:832dc0e10feb1aa2c68dcc57dbb658f1c7e65b9b61af69048abc87a2db00a0eb"
+ ],
+ "version": "==1.11.0"
+ }
+ }
+}
diff --git a/uv/spec/fixtures/poetry_locks/caret_version.lock b/uv/spec/fixtures/poetry_locks/caret_version.lock
new file mode 100644
index 00000000000..05beda41dba
--- /dev/null
+++ b/uv/spec/fixtures/poetry_locks/caret_version.lock
@@ -0,0 +1,16 @@
+[[package]]
+category = "main"
+description = "Python HTTP for Humans."
+name = "requests"
+optional = false
+platform = "UNKNOWN"
+python-versions = "*"
+version = "1.2.3"
+
+[metadata]
+content-hash = "8289fd2c93ad6e51a8a4f52ac2211d4234480e062a998bc4db6dd28c9c78dbe2"
+platform = "*"
+python-versions = "^3.7"
+
+[metadata.hashes]
+requests = ["156bf3ec27ba9ec7e0cf8fbe02808718099d218de403eb64a714d73ba1a29ab1"]
diff --git a/uv/spec/fixtures/poetry_locks/conflict_at_latest.lock b/uv/spec/fixtures/poetry_locks/conflict_at_latest.lock
new file mode 100644
index 00000000000..76faaad1c28
--- /dev/null
+++ b/uv/spec/fixtures/poetry_locks/conflict_at_latest.lock
@@ -0,0 +1,100 @@
+[[package]]
+category = "dev"
+description = "Classes Without Boilerplate"
+name = "attrs"
+optional = false
+platform = "*"
+python-versions = "*"
+version = "18.1.0"
+
+[[package]]
+category = "main"
+description = "Universal encoding detector for Python 2 and 3"
+name = "chardet"
+optional = false
+platform = "*"
+python-versions = "*"
+version = "3.0.0"
+
+[[package]]
+category = "dev"
+description = "Cross-platform colored terminal text."
+name = "colorama"
+optional = false
+platform = "UNKNOWN"
+python-versions = "*"
+version = "0.3.9"
+
+[package.requirements]
+platform = "win32"
+
+[[package]]
+category = "dev"
+description = "plugin and hook calling mechanisms for python"
+name = "pluggy"
+optional = false
+platform = "unix"
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+version = "0.6.0"
+
+[[package]]
+category = "dev"
+description = "library with cross-python path, ini-parsing, io, code, log facilities"
+name = "py"
+optional = false
+platform = "unix"
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+version = "1.5.4"
+
+[[package]]
+category = "dev"
+description = "pytest: simple powerful testing with Python"
+name = "pytest"
+optional = false
+platform = "*"
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+version = "3.4.0"
+
+[package.dependencies]
+attrs = ">=17.2.0"
+pluggy = ">=0.5,<0.7"
+py = ">=1.5.0"
+setuptools = "*"
+six = ">=1.10.0"
+
+[package.dependencies.colorama]
+platform = "win32"
+version = "*"
+
+[[package]]
+category = "main"
+description = "Python HTTP for Humans."
+name = "requests"
+optional = false
+platform = "UNKNOWN"
+python-versions = "*"
+version = "2.6.0"
+
+[[package]]
+category = "dev"
+description = "Python 2 and 3 compatibility utilities"
+name = "six"
+optional = false
+platform = "*"
+python-versions = "*"
+version = "1.11.0"
+
+[metadata]
+content-hash = "eae25082e355381411c3f71fde8ff26a0d09429d27f4ad6272faea571a2311b5"
+platform = "*"
+python-versions = "^3.7"
+
+[metadata.hashes]
+attrs = ["4b90b09eeeb9b88c35bc642cbac057e45a5fd85367b985bd2809c62b7b939265", "e0d0eb91441a3b53dab4d9b743eafc1ac44476296a2053b6ca3af0b139faf87b"]
+chardet = ["171dfc754d56c16b82cf77ac3eee1d42db9bc2f26c2c61c6573426d2a108d9e3", "bedd581d3daea4180b3cb555940dcbc89916e7922b070d2a9a37e660791e90a2"]
+colorama = ["463f8483208e921368c9f306094eb6f725c6ca42b0f97e313cb5d5512459feda", "48eb22f4f8461b1df5734a074b57042430fb06e1d61bd1e11b078c0fe6d7a1f1"]
+pluggy = ["7f8ae7f5bdf75671a718d2daf0a64b7885f74510bcd98b1a0bb420eb9a9d0cff", "d345c8fe681115900d6da8d048ba67c25df42973bda370783cd58826442dcd7c", "e160a7fcf25762bb60efc7e171d4497ff1d8d2d75a3d0df7a21b76821ecbf5c5"]
+py = ["3fd59af7435864e1a243790d322d763925431213b6b8529c6ca71081ace3bbf7", "e31fb2767eb657cbde86c454f02e99cb846d3cd9d61b318525140214fdc0e98e"]
+pytest = ["6074ea3b9c999bd6d0df5fa9d12dd95ccd23550df2a582f5f5b848331d2e82ca", "95fa025cd6deb5d937e04e368a00552332b58cae23f63b76c8c540ff1733ab6d"]
+requests = ["1cdbed1f0e236f35ef54e919982c7a338e4fea3786310933d3a7887a04b74d75", "fdb9af60d47ca57a80df0a213336019a34ff6192d8fff361c349f2c8398fe460"]
+six = ["70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9", "832dc0e10feb1aa2c68dcc57dbb658f1c7e65b9b61af69048abc87a2db00a0eb"]
diff --git a/uv/spec/fixtures/poetry_locks/dir_dependency.lock b/uv/spec/fixtures/poetry_locks/dir_dependency.lock
new file mode 100644
index 00000000000..2ef002eb5e4
--- /dev/null
+++ b/uv/spec/fixtures/poetry_locks/dir_dependency.lock
@@ -0,0 +1,195 @@
+# This file is automatically @generated by Poetry 1.6.1 and should not be changed by hand.
+
+[[package]]
+name = "atomicwrites"
+version = "1.4.1"
+description = "Atomic file writes."
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+files = [
+ {file = "atomicwrites-1.4.1.tar.gz", hash = "sha256:81b2c9071a49367a7f770170e5eec8cb66567cfbbc8c73d20ce5ca4a8d71cf11"},
+]
+
+[[package]]
+name = "attrs"
+version = "23.1.0"
+description = "Classes Without Boilerplate"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "attrs-23.1.0-py3-none-any.whl", hash = "sha256:1f28b4522cdc2fb4256ac1a020c78acf9cba2c6b461ccd2c126f3aa8e8335d04"},
+ {file = "attrs-23.1.0.tar.gz", hash = "sha256:6279836d581513a26f1bf235f9acd333bc9115683f14f7e8fae46c98fc50e015"},
+]
+
+[package.dependencies]
+importlib-metadata = {version = "*", markers = "python_version < \"3.8\""}
+
+[package.extras]
+cov = ["attrs[tests]", "coverage[toml] (>=5.3)"]
+dev = ["attrs[docs,tests]", "pre-commit"]
+docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope-interface"]
+tests = ["attrs[tests-no-zope]", "zope-interface"]
+tests-no-zope = ["cloudpickle", "hypothesis", "mypy (>=1.1.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"]
+
+[[package]]
+name = "colorama"
+version = "0.4.6"
+description = "Cross-platform colored terminal text."
+optional = false
+python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
+files = [
+ {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"},
+ {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
+]
+
+[[package]]
+name = "importlib-metadata"
+version = "6.7.0"
+description = "Read metadata from Python packages"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "importlib_metadata-6.7.0-py3-none-any.whl", hash = "sha256:cb52082e659e97afc5dac71e79de97d8681de3aa07ff18578330904a9d18e5b5"},
+ {file = "importlib_metadata-6.7.0.tar.gz", hash = "sha256:1aaf550d4f73e5d6783e7acb77aec43d49da8017410afae93822cc9cca98c4d4"},
+]
+
+[package.dependencies]
+typing-extensions = {version = ">=3.6.4", markers = "python_version < \"3.8\""}
+zipp = ">=0.5"
+
+[package.extras]
+docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"]
+perf = ["ipython"]
+testing = ["flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)", "pytest-ruff"]
+
+[[package]]
+name = "more-itertools"
+version = "9.1.0"
+description = "More routines for operating on iterables, beyond itertools"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "more-itertools-9.1.0.tar.gz", hash = "sha256:cabaa341ad0389ea83c17a94566a53ae4c9d07349861ecb14dc6d0345cf9ac5d"},
+ {file = "more_itertools-9.1.0-py3-none-any.whl", hash = "sha256:d2bc7f02446e86a68911e58ded76d6561eea00cddfb2a91e7019bbb586c799f3"},
+]
+
+[[package]]
+name = "pluggy"
+version = "1.2.0"
+description = "plugin and hook calling mechanisms for python"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "pluggy-1.2.0-py3-none-any.whl", hash = "sha256:c2fd55a7d7a3863cba1a013e4e2414658b1d07b6bc57b3919e0c63c9abb99849"},
+ {file = "pluggy-1.2.0.tar.gz", hash = "sha256:d12f0c4b579b15f5e054301bb226ee85eeeba08ffec228092f8defbaa3a4c4b3"},
+]
+
+[package.dependencies]
+importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""}
+
+[package.extras]
+dev = ["pre-commit", "tox"]
+testing = ["pytest", "pytest-benchmark"]
+
+[[package]]
+name = "py"
+version = "1.11.0"
+description = "library with cross-python path, ini-parsing, io, code, log facilities"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
+files = [
+ {file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"},
+ {file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"},
+]
+
+[[package]]
+name = "pytest"
+version = "3.7.4"
+description = "pytest: simple powerful testing with Python"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+files = [
+ {file = "pytest-3.7.4-py2.py3-none-any.whl", hash = "sha256:ad0c7db7b5d4081631e0155f5c61b80ad76ce148551aaafe3a718d65a7508b18"},
+ {file = "pytest-3.7.4.tar.gz", hash = "sha256:2d7c49e931316cc7d1638a3e5f54f5d7b4e5225972b3c9838f3584788d27f349"},
+]
+
+[package.dependencies]
+atomicwrites = ">=1.0"
+attrs = ">=17.4.0"
+colorama = {version = "*", markers = "sys_platform == \"win32\""}
+more-itertools = ">=4.0.0"
+pluggy = ">=0.7"
+py = ">=1.5.0"
+setuptools = "*"
+six = ">=1.10.0"
+
+[[package]]
+name = "setuptools"
+version = "68.0.0"
+description = "Easily download, build, install, upgrade, and uninstall Python packages"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "setuptools-68.0.0-py3-none-any.whl", hash = "sha256:11e52c67415a381d10d6b462ced9cfb97066179f0e871399e006c4ab101fc85f"},
+ {file = "setuptools-68.0.0.tar.gz", hash = "sha256:baf1fdb41c6da4cd2eae722e135500da913332ab3f2f5c7d33af9b492acb5235"},
+]
+
+[package.extras]
+docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-hoverxref (<2)", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (==0.8.3)", "sphinx-reredirects", "sphinxcontrib-towncrier"]
+testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pip-run (>=8.8)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"]
+testing-integration = ["build[virtualenv]", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"]
+
+[[package]]
+name = "six"
+version = "1.16.0"
+description = "Python 2 and 3 compatibility utilities"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*"
+files = [
+ {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"},
+ {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"},
+]
+
+[[package]]
+name = "toml"
+version = "0.10.0"
+description = ""
+optional = false
+python-versions = "*"
+files = []
+develop = false
+
+[package.source]
+type = "directory"
+url = "../toml"
+
+[[package]]
+name = "typing-extensions"
+version = "4.7.1"
+description = "Backported and Experimental Type Hints for Python 3.7+"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "typing_extensions-4.7.1-py3-none-any.whl", hash = "sha256:440d5dd3af93b060174bf433bccd69b0babc3b15b1a8dca43789fd7f61514b36"},
+ {file = "typing_extensions-4.7.1.tar.gz", hash = "sha256:b75ddc264f0ba5615db7ba217daeb99701ad295353c45f9e95963337ceeeffb2"},
+]
+
+[[package]]
+name = "zipp"
+version = "3.15.0"
+description = "Backport of pathlib-compatible object wrapper for zip files"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "zipp-3.15.0-py3-none-any.whl", hash = "sha256:48904fc76a60e542af151aded95726c1a5c34ed43ab4134b597665c86d7ad556"},
+ {file = "zipp-3.15.0.tar.gz", hash = "sha256:112929ad649da941c23de50f356a2b5570c954b65150642bccdd66bf194d224b"},
+]
+
+[package.extras]
+docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"]
+testing = ["big-O", "flake8 (<5)", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)"]
+
+[metadata]
+lock-version = "2.0"
+python-versions = "^3.7"
+content-hash = "282f615475785b19b24fdb9205c2f22a16e1162bc1ae56f8d9d17ee68dcf5119"
diff --git a/uv/spec/fixtures/poetry_locks/exact_version.lock b/uv/spec/fixtures/poetry_locks/exact_version.lock
new file mode 100644
index 00000000000..563bb5509a3
--- /dev/null
+++ b/uv/spec/fixtures/poetry_locks/exact_version.lock
@@ -0,0 +1,62 @@
+[[package]]
+category = "main"
+description = "Python package for providing Mozilla's CA Bundle."
+name = "certifi"
+optional = false
+platform = "*"
+python-versions = "*"
+version = "2018.4.16"
+
+[[package]]
+category = "main"
+description = "Universal encoding detector for Python 2 and 3"
+name = "chardet"
+optional = false
+platform = "*"
+python-versions = "*"
+version = "3.0.4"
+
+[[package]]
+category = "main"
+description = "Internationalized Domain Names in Applications (IDNA)"
+name = "idna"
+optional = false
+platform = "UNKNOWN"
+python-versions = "*"
+version = "2.5"
+
+[[package]]
+category = "main"
+description = "Python HTTP for Humans."
+name = "requests"
+optional = false
+platform = "*"
+python-versions = "*"
+version = "2.18.0"
+
+[package.dependencies]
+certifi = ">=2017.4.17"
+chardet = ">=3.0.2,<3.1.0"
+idna = ">=2.5,<2.6"
+urllib3 = ">=1.21.1,<1.22"
+
+[[package]]
+category = "main"
+description = "HTTP library with thread-safe connection pooling, file post, and more."
+name = "urllib3"
+optional = false
+platform = "*"
+python-versions = "*"
+version = "1.21.1"
+
+[metadata]
+content-hash = "a8d5762e953227a34625a209e9cc67a1c6fb2d7a971845829cf2f9cf61a5bd7c"
+platform = "*"
+python-versions = "*"
+
+[metadata.hashes]
+certifi = ["13e698f54293db9f89122b0581843a782ad0934a4fe0172d2a980ba77fc61bb7", "9fa520c1bacfb634fa7af20a76bcbd3d5fb390481724c597da32c719a7dca4b0"]
+chardet = ["84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae", "fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"]
+idna = ["3cb5ce08046c4e3a560fc02f138d0ac63e00f8ce5901a56b32ec8b7994082aab", "cc19709fd6d0cbfed39ea875d29ba6d4e22c0cebc510a76d6302a28385e8bb70"]
+requests = ["5e88d64aa56ac0fda54e77fb9762ebc65879e171b746d5479a33c4082519d6c6", "cd0189f962787284bff715fddaad478eb4d9c15aa167bd64e52ea0f661e7ea5c"]
+urllib3 = ["8ed6d5c1ff9d6ba84677310060d6a3a78ca3072ce0684cb3c645023009c114b1", "b14486978518ca0901a76ba973d7821047409d7f726f22156b24e83fd71382a5"]
diff --git a/uv/spec/fixtures/poetry_locks/extra_dependency.lock b/uv/spec/fixtures/poetry_locks/extra_dependency.lock
new file mode 100644
index 00000000000..aa2e88cfde7
--- /dev/null
+++ b/uv/spec/fixtures/poetry_locks/extra_dependency.lock
@@ -0,0 +1,72 @@
+[[package]]
+category = "main"
+description = "Python package for providing Mozilla's CA Bundle."
+name = "certifi"
+optional = false
+platform = "*"
+python-versions = "*"
+version = "2018.4.16"
+
+[[package]]
+category = "dev"
+description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers."
+marker = "python_version < \"3\" and extra == \"secure\""
+name = "cryptography"
+optional = false
+python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*"
+version = "2.4.2"
+
+[[package]]
+category = "main"
+description = "Universal encoding detector for Python 2 and 3"
+name = "chardet"
+optional = false
+platform = "*"
+python-versions = "*"
+version = "3.0.4"
+
+[[package]]
+category = "main"
+description = "Internationalized Domain Names in Applications (IDNA)"
+name = "idna"
+optional = false
+platform = "UNKNOWN"
+python-versions = "*"
+version = "2.5"
+
+[[package]]
+category = "main"
+description = "Python HTTP for Humans."
+name = "requests"
+optional = false
+platform = "*"
+python-versions = "*"
+version = "2.18.0"
+
+[package.dependencies]
+certifi = ">=2017.4.17"
+chardet = ">=3.0.2,<3.1.0"
+idna = ">=2.5,<2.6"
+urllib3 = ">=1.21.1,<1.22"
+
+[[package]]
+category = "main"
+description = "HTTP library with thread-safe connection pooling, file post, and more."
+name = "urllib3"
+optional = false
+platform = "*"
+python-versions = "*"
+version = "1.21.1"
+
+[metadata]
+content-hash = "a8d5762e953227a34625a209e9cc67a1c6fb2d7a971845829cf2f9cf61a5bd7c"
+platform = "*"
+python-versions = "^3.7"
+
+[metadata.hashes]
+certifi = ["13e698f54293db9f89122b0581843a782ad0934a4fe0172d2a980ba77fc61bb7", "9fa520c1bacfb634fa7af20a76bcbd3d5fb390481724c597da32c719a7dca4b0"]
+chardet = ["84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae", "fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"]
+cryptography = ["05a6052c6a9f17ff78ba78f8e6eb1d777d25db3b763343a1ae89a7a8670386dd", "0eb83a24c650a36f68e31a6d0a70f7ad9c358fa2506dc7b683398b92e354a038", "0ff4a3d6ea86aa0c9e06e92a9f986de7ee8231f36c4da1b31c61a7e692ef3378", "1699f3e916981df32afdd014fb3164db28cdb61c757029f502cb0a8c29b2fdb3", "1b1f136d74f411f587b07c076149c4436a169dc19532e587460d9ced24adcc13", "21e63dd20f5e5455e8b34179ac43d95b3fb1ffa54d071fd2ed5d67da82cfe6dc", "2454ada8209bbde97065453a6ca488884bbb263e623d35ba183821317a58b46f", "3cdc5f7ca057b2214ce4569e01b0f368b3de9d8ee01887557755ccd1c15d9427", "418e7a5ec02a7056d3a4f0c0e7ea81df374205f25f4720bb0e84189aa5fd2515", "471a097076a7c4ab85561d7fa9a1239bd2ae1f9fd0047520f13d8b340bf3210b", "5ecaf9e7db3ca582c6de6229525d35db8a4e59dc3e8a40a331674ed90e658cbf", "63b064a074f8dc61be81449796e2c3f4e308b6eba04a241a5c9f2d05e882c681", "6afe324dfe6074822ccd56d80420df750e19ac30a4e56c925746c735cf22ae8b", "70596e90398574b77929cd87e1ac6e43edd0e29ba01e1365fed9c26bde295aa5", "70c2b04e905d3f72e2ba12c58a590817128dfca08949173faa19a42c824efa0b", "8908f1db90be48b060888e9c96a0dee9d842765ce9594ff6a23da61086116bb6", "af12dfc9874ac27ebe57fc28c8df0e8afa11f2a1025566476b0d50cdb8884f70", "b4fc04326b2d259ddd59ed8ea20405d2e695486ab4c5e1e49b025c484845206e", "da5b5dda4aa0d5e2b758cc8dfc67f8d4212e88ea9caad5f61ba132f948bab859"]
+idna = ["3cb5ce08046c4e3a560fc02f138d0ac63e00f8ce5901a56b32ec8b7994082aab", "cc19709fd6d0cbfed39ea875d29ba6d4e22c0cebc510a76d6302a28385e8bb70"]
+requests = ["5e88d64aa56ac0fda54e77fb9762ebc65879e171b746d5479a33c4082519d6c6", "cd0189f962787284bff715fddaad478eb4d9c15aa167bd64e52ea0f661e7ea5c"]
+urllib3 = ["8ed6d5c1ff9d6ba84677310060d6a3a78ca3072ce0684cb3c645023009c114b1", "b14486978518ca0901a76ba973d7821047409d7f726f22156b24e83fd71382a5"]
diff --git a/uv/spec/fixtures/poetry_locks/extras.lock b/uv/spec/fixtures/poetry_locks/extras.lock
new file mode 100644
index 00000000000..8280cc6baa7
--- /dev/null
+++ b/uv/spec/fixtures/poetry_locks/extras.lock
@@ -0,0 +1,258 @@
+[[package]]
+category = "main"
+description = "Low-level AMQP client for Python (fork of amqplib)."
+name = "amqp"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+version = "2.5.0"
+
+[package.dependencies]
+vine = ">=1.1.3,<5.0.0a1"
+
+[[package]]
+category = "dev"
+description = "Disable App Nap on OS X 10.9"
+marker = "sys_platform == \"darwin\""
+name = "appnope"
+optional = false
+python-versions = "*"
+version = "0.1.0"
+
+[[package]]
+category = "dev"
+description = "Specifications for callback functions passed in to an API"
+name = "backcall"
+optional = false
+python-versions = "*"
+version = "0.1.0"
+
+[[package]]
+category = "main"
+description = "Python multiprocessing fork with improvements and bugfixes"
+name = "billiard"
+optional = false
+python-versions = "*"
+version = "3.6.0.0"
+
+[[package]]
+category = "main"
+description = "Distributed Task Queue."
+name = "celery"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+version = "4.3.0"
+
+[package.dependencies]
+billiard = ">=3.6.0,<4.0"
+kombu = ">=4.4.0,<5.0"
+pytz = ">0.0-dev"
+redis = ">=3.2.0"
+vine = ">=1.3.0"
+
+[[package]]
+category = "dev"
+description = "Cross-platform colored terminal text."
+marker = "sys_platform == \"win32\""
+name = "colorama"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+version = "0.4.1"
+
+[[package]]
+category = "dev"
+description = "Better living through Python with decorators"
+name = "decorator"
+optional = false
+python-versions = ">=2.6, !=3.0.*, !=3.1.*"
+version = "4.4.0"
+
+[[package]]
+category = "dev"
+description = "IPython: Productive Interactive Computing"
+name = "ipython"
+optional = false
+python-versions = ">=3.5"
+version = "7.5.0"
+
+[package.dependencies]
+appnope = "*"
+backcall = "*"
+colorama = "*"
+decorator = "*"
+jedi = ">=0.10"
+pexpect = "*"
+pickleshare = "*"
+prompt-toolkit = ">=2.0.0,<2.1.0"
+pygments = "*"
+setuptools = ">=18.5"
+traitlets = ">=4.2"
+
+[[package]]
+category = "dev"
+description = "Vestigial utilities from IPython"
+name = "ipython-genutils"
+optional = false
+python-versions = "*"
+version = "0.2.0"
+
+[[package]]
+category = "dev"
+description = "An autocompletion tool for Python that can be used for text editors."
+name = "jedi"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+version = "0.14.1"
+
+[package.dependencies]
+parso = ">=0.5.0"
+
+[[package]]
+category = "main"
+description = "Messaging library for Python."
+name = "kombu"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
+version = "4.6.3"
+
+[package.dependencies]
+amqp = ">=2.5.0,<3.0"
+
+[[package]]
+category = "dev"
+description = "A Python Parser"
+name = "parso"
+optional = false
+python-versions = "*"
+version = "0.5.1"
+
+[[package]]
+category = "dev"
+description = "Pexpect allows easy control of interactive console applications."
+marker = "sys_platform != \"win32\""
+name = "pexpect"
+optional = false
+python-versions = "*"
+version = "4.7.0"
+
+[package.dependencies]
+ptyprocess = ">=0.5"
+
+[[package]]
+category = "dev"
+description = "Tiny 'shelve'-like database with concurrency support"
+name = "pickleshare"
+optional = false
+python-versions = "*"
+version = "0.7.5"
+
+[[package]]
+category = "dev"
+description = "Library for building powerful interactive command lines in Python"
+name = "prompt-toolkit"
+optional = false
+python-versions = "*"
+version = "2.0.9"
+
+[package.dependencies]
+six = ">=1.9.0"
+wcwidth = "*"
+
+[[package]]
+category = "dev"
+description = "Run a subprocess in a pseudo terminal"
+marker = "sys_platform != \"win32\""
+name = "ptyprocess"
+optional = false
+python-versions = "*"
+version = "0.6.0"
+
+[[package]]
+category = "dev"
+description = "Pygments is a syntax highlighting package written in Python."
+name = "pygments"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
+version = "2.4.2"
+
+[[package]]
+category = "main"
+description = "World timezone definitions, modern and historical"
+name = "pytz"
+optional = false
+python-versions = "*"
+version = "2019.1"
+
+[[package]]
+category = "main"
+description = "Python client for Redis key-value store"
+marker = "extra == \"redis\""
+name = "redis"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+version = "3.2.1"
+
+[[package]]
+category = "dev"
+description = "Python 2 and 3 compatibility utilities"
+name = "six"
+optional = false
+python-versions = ">=2.6, !=3.0.*, !=3.1.*"
+version = "1.12.0"
+
+[[package]]
+category = "dev"
+description = "Traitlets Python config system"
+name = "traitlets"
+optional = false
+python-versions = "*"
+version = "4.3.2"
+
+[package.dependencies]
+decorator = "*"
+ipython-genutils = "*"
+six = "*"
+
+[[package]]
+category = "main"
+description = "Promises, promises, promises."
+name = "vine"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+version = "1.3.0"
+
+[[package]]
+category = "dev"
+description = "Measures number of Terminal column cells of wide-character codes"
+name = "wcwidth"
+optional = false
+python-versions = "*"
+version = "0.1.7"
+
+[metadata]
+content-hash = "2cc62098874ebb107501ade23941133fbe6560d9614d2920548236f314316ab7"
+python-versions = "^3.7"
+
+[metadata.hashes]
+amqp = ["aa4409446139676943a2eaa27d5f58caf750f4ca5a89f888c452afd86be6a67d", "cbb6f87d53cac612a594f982b717cc1c54c6a1e17943a0a0d32dc6cc9e2120c8"]
+appnope = ["5b26757dc6f79a3b7dc9fab95359328d5747fcb2409d331ea66d0272b90ab2a0", "8b995ffe925347a2138d7ac0fe77155e4311a0ea6d6da4f5128fe4b3cbe5ed71"]
+backcall = ["38ecd85be2c1e78f77fd91700c76e14667dc21e2713b63876c0eb901196e01e4", "bbbf4b1e5cd2bdb08f915895b51081c041bac22394fdfcfdfbe9f14b77c08bf2"]
+billiard = ["756bf323f250db8bf88462cd042c992ba60d8f5e07fc5636c24ba7d6f4261d84"]
+celery = ["4c4532aa683f170f40bd76f928b70bc06ff171a959e06e71bf35f2f9d6031ef9", "528e56767ae7e43a16cfef24ee1062491f5754368d38fcfffa861cdb9ef219be"]
+colorama = ["05eed71e2e327246ad6b38c540c4a3117230b19679b875190486ddd2d721422d", "f8ac84de7840f5b9c4e3347b3c1eaa50f7e49c2b07596221daec5edaabbd7c48"]
+decorator = ["86156361c50488b84a3f148056ea716ca587df2f0de1d34750d35c21312725de", "f069f3a01830ca754ba5258fde2278454a0b5b79e0d7f5c13b3b97e57d4acff6"]
+ipython = ["54c5a8aa1eadd269ac210b96923688ccf01ebb2d0f21c18c3c717909583579a8", "e840810029224b56cd0d9e7719dc3b39cf84d577f8ac686547c8ba7a06eeab26"]
+ipython-genutils = ["72dd37233799e619666c9f639a9da83c34013a73e8bbc79a7a6348d93c61fab8", "eb2e116e75ecef9d4d228fdc66af54269afa26ab4463042e33785b887c628ba8"]
+jedi = ["53c850f1a7d3cfcd306cc513e2450a54bdf5cacd7604b74e42dd1f0758eaaf36", "e07457174ef7cb2342ff94fa56484fe41cec7ef69b0059f01d3f812379cb6f7c"]
+kombu = ["55b71d3785def3470a16217fe0780f9e6f95e61bf9ad39ef8dce0177224eab77", "eb365ea795cd7e629ba2f1f398e0c3ba354b91ef4de225ffdf6ab45fdfc7d581"]
+parso = ["63854233e1fadb5da97f2744b6b24346d2750b85965e7e399bec1620232797dc", "666b0ee4a7a1220f65d367617f2cd3ffddff3e205f3f16a0284df30e774c2a9c"]
+pexpect = ["2094eefdfcf37a1fdbfb9aa090862c1a4878e5c7e0e7e7088bdb511c558e5cd1", "9e2c1fd0e6ee3a49b28f95d4b33bc389c89b20af6a1255906e90ff1262ce62eb"]
+pickleshare = ["87683d47965c1da65cdacaf31c8441d12b8044cdec9aca500cd78fc2c683afca", "9649af414d74d4df115d5d718f82acb59c9d418196b7b4290ed47a12ce62df56"]
+prompt-toolkit = ["11adf3389a996a6d45cc277580d0d53e8a5afd281d0c9ec71b28e6f121463780", "2519ad1d8038fd5fc8e770362237ad0364d16a7650fb5724af6997ed5515e3c1", "977c6583ae813a37dc1c2e1b715892461fcbdaa57f6fc62f33a528c4886c8f55"]
+ptyprocess = ["923f299cc5ad920c68f2bc0bc98b75b9f838b93b599941a6b63ddbc2476394c0", "d7cc528d76e76342423ca640335bd3633420dc1366f258cb31d05e865ef5ca1f"]
+pygments = ["71e430bc85c88a430f000ac1d9b331d2407f681d6f6aec95e8bcfbc3df5b0127", "881c4c157e45f30af185c1ffe8d549d48ac9127433f2c380c24b84572ad66297"]
+pytz = ["303879e36b721603cc54604edcac9d20401bdbe31e1e4fdee5b9f98d5d31dfda", "d747dd3d23d77ef44c6a3526e274af6efeb0a6f1afd5a69ba4d5be4098c8e141"]
+redis = ["6946b5dca72e86103edc8033019cc3814c031232d339d5f4533b02ea85685175", "8ca418d2ddca1b1a850afa1680a7d2fd1f3322739271de4b704e0d4668449273"]
+six = ["3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c", "d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73"]
+traitlets = ["9c4bd2d267b7153df9152698efb1050a5d84982d3384a37b2c1f7723ba3e7835", "c6cb5e6f57c5a9bdaa40fa71ce7b4af30298fbab9ece9815b5d995ab6217c7d9"]
+vine = ["133ee6d7a9016f177ddeaf191c1f58421a1dcc6ee9a42c58b34bed40e1d2cd87", "ea4947cc56d1fd6f2095c8d543ee25dad966f78692528e68b4fada11ba3f98af"]
+wcwidth = ["3df37372226d6e63e1b1e1eda15c594bca98a22d33a23832a90998faa96bc65e", "f4ebe71925af7b40a864553f761ed559b43544f8f71746c2d756c7fe788ade7c"]
diff --git a/uv/spec/fixtures/poetry_locks/file_dependency.lock b/uv/spec/fixtures/poetry_locks/file_dependency.lock
new file mode 100644
index 00000000000..c18693f8ee9
--- /dev/null
+++ b/uv/spec/fixtures/poetry_locks/file_dependency.lock
@@ -0,0 +1,114 @@
+[[package]]
+category = "main"
+description = "Atomic file writes."
+name = "atomicwrites"
+optional = false
+platform = "*"
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+version = "1.2.1"
+
+[[package]]
+category = "main"
+description = "Classes Without Boilerplate"
+name = "attrs"
+optional = false
+platform = "*"
+python-versions = "*"
+version = "18.2.0"
+
+[[package]]
+category = "main"
+description = "Cross-platform colored terminal text."
+name = "colorama"
+optional = false
+platform = "UNKNOWN"
+python-versions = "*"
+version = "0.3.9"
+
+[package.requirements]
+platform = "win32"
+
+[[package]]
+category = "main"
+description = "More routines for operating on iterables, beyond itertools"
+name = "more-itertools"
+optional = false
+platform = "*"
+python-versions = "*"
+version = "4.3.0"
+
+[package.dependencies]
+six = ">=1.0.0,<2.0.0"
+
+[[package]]
+category = "main"
+description = "plugin and hook calling mechanisms for python"
+name = "pluggy"
+optional = false
+platform = "unix"
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+version = "0.7.1"
+
+[[package]]
+category = "main"
+description = "library with cross-python path, ini-parsing, io, code, log facilities"
+name = "py"
+optional = false
+platform = "unix"
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+version = "1.6.0"
+
+[[package]]
+category = "main"
+description = "pytest: simple powerful testing with Python"
+name = "pytest"
+optional = false
+platform = "unix"
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+version = "3.7.4"
+
+[package.dependencies]
+atomicwrites = ">=1.0"
+attrs = ">=17.4.0"
+more-itertools = ">=4.0.0"
+pluggy = ">=0.7"
+py = ">=1.5.0"
+setuptools = "*"
+six = ">=1.10.0"
+
+[package.dependencies.colorama]
+platform = "win32"
+version = "*"
+
+[[package]]
+category = "main"
+description = "Python 2 and 3 compatibility utilities"
+name = "six"
+optional = false
+platform = "*"
+python-versions = "*"
+version = "1.11.0"
+
+[[package]]
+category = "main"
+description = ""
+name = "toml"
+optional = false
+platform = "*"
+python-versions = "*"
+version = "0.10.0"
+
+[package.source]
+type = "file"
+url = "toml-8.2.54.tar.gz"
+
+[metadata.hashes]
+atomicwrites = ["0312ad34fcad8fac3704d441f7b317e50af620823353ec657a53e981f92920c0", "ec9ae8adaae229e4f8446952d204a3e4b5fdd2d099f9be3aaf556120135fb3ee"]
+attrs = ["10cbf6e27dbce8c30807caf056c8eb50917e0eaafe86347671b57254006c3e69", "ca4be454458f9dec299268d472aaa5a11f67a4ff70093396e1ceae9c76cf4bbb"]
+colorama = ["463f8483208e921368c9f306094eb6f725c6ca42b0f97e313cb5d5512459feda", "48eb22f4f8461b1df5734a074b57042430fb06e1d61bd1e11b078c0fe6d7a1f1"]
+more-itertools = ["c187a73da93e7a8acc0001572aebc7e3c69daf7bf6881a2cea10650bd4420092", "c476b5d3a34e12d40130bc2f935028b5f636df8f372dc2c1c01dc19681b2039e", "fcbfeaea0be121980e15bc97b3817b5202ca73d0eae185b4550cbfce2a3ebb3d"]
+pluggy = ["6e3836e39f4d36ae72840833db137f7b7d35105079aee6ec4a62d9f80d594dd1", "95eb8364a4708392bae89035f45341871286a333f749c3141c20573d2b3876e1"]
+py = ["06a30435d058473046be836d3fc4f27167fd84c45b99704f2fb5509ef61f9af1", "50402e9d1c9005d759426988a492e0edaadb7f4e68bcddfea586bc7432d009c6"]
+pytest = ["2d7c49e931316cc7d1638a3e5f54f5d7b4e5225972b3c9838f3584788d27f349", "ad0c7db7b5d4081631e0155f5c61b80ad76ce148551aaafe3a718d65a7508b18"]
+six = ["70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9", "832dc0e10feb1aa2c68dcc57dbb658f1c7e65b9b61af69048abc87a2db00a0eb"]
+toml = []
diff --git a/uv/spec/fixtures/poetry_locks/git_conflict.lock b/uv/spec/fixtures/poetry_locks/git_conflict.lock
new file mode 100644
index 00000000000..06412a93266
--- /dev/null
+++ b/uv/spec/fixtures/poetry_locks/git_conflict.lock
@@ -0,0 +1,739 @@
+[[package]]
+category = "main"
+description = "Bash tab completion for argparse"
+name = "argcomplete"
+optional = false
+platform = "MacOS X"
+python-versions = "*"
+version = "1.8.2"
+
+[[package]]
+category = "main"
+description = "Screen-scraping library"
+name = "beautifulsoup4"
+optional = false
+platform = "UNKNOWN"
+python-versions = "*"
+version = "4.6.0"
+
+[[package]]
+category = "main"
+description = "Python package for providing Mozilla's CA Bundle."
+name = "certifi"
+optional = false
+platform = "*"
+python-versions = "*"
+version = "2018.8.24"
+
+[[package]]
+category = "main"
+description = "Universal encoding detector for Python 2 and 3"
+name = "chardet"
+optional = false
+platform = "*"
+python-versions = "*"
+version = "3.0.4"
+
+[[package]]
+category = "main"
+description = "A simple wrapper around optparse for powerful command line utilities."
+name = "click"
+optional = false
+platform = "*"
+python-versions = "*"
+version = "6.7"
+
+[[package]]
+category = "main"
+description = "A high-level Python Web framework that encourages rapid development and clean, pragmatic design."
+name = "django"
+optional = false
+platform = "*"
+python-versions = "*"
+version = "1.11.15"
+
+[package.dependencies]
+pytz = "*"
+
+[[package]]
+category = "main"
+description = "Integrated set of Django applications addressing authentication, registration, account management as well as 3rd party (social) account authentication."
+name = "django-allauth"
+optional = false
+platform = "*"
+python-versions = "*"
+version = "0.37.1"
+
+[package.dependencies]
+Django = ">=1.11"
+python-openid = ">=2.2.5"
+requests = "*"
+requests-oauthlib = ">=0.3.0"
+
+[[package]]
+category = "main"
+description = "Django email integration for Amazon SES, Mailgun, Mailjet, Postmark, SendGrid, SendinBlue, SparkPost and other transactional ESPs"
+name = "django-anymail"
+optional = false
+platform = "*"
+python-versions = "*"
+version = "4.1"
+
+[package.dependencies]
+django = ">=1.11"
+requests = ">=2.4.3"
+six = "*"
+
+[[package]]
+category = "main"
+description = "Reusable, generic mixins for Django"
+name = "django-braces"
+optional = false
+platform = "*"
+python-versions = "*"
+version = "1.13.0"
+
+[[package]]
+category = "main"
+description = "Django Content Security Policy support."
+name = "django-csp"
+optional = false
+platform = "*"
+python-versions = "*"
+version = "3.4"
+
+[package.dependencies]
+Django = ">=1.8"
+
+[[package]]
+category = "main"
+description = "A configurable set of panels that display various debug information about the current request/response."
+name = "django-debug-toolbar"
+optional = false
+platform = "*"
+python-versions = "*"
+version = "1.9.1"
+
+[package.dependencies]
+Django = ">=1.8"
+sqlparse = ">=0.2.0"
+
+[[package]]
+category = "main"
+description = "Wrapper around elasticsearch-dsl-py for django models"
+name = "django-elasticsearch-dsl"
+optional = false
+platform = "*"
+python-versions = "*"
+version = "0.4.5"
+
+[package.dependencies]
+elasticsearch-dsl = ">=2.1.0,<6.0.0"
+
+[[package]]
+category = "main"
+description = "Django-environ allows you to utilize 12factor inspired environment variables to configure your Django application."
+name = "django-environ"
+optional = false
+platform = "any"
+python-versions = "*"
+version = "0.4.5"
+
+[[package]]
+category = "main"
+description = "Serve vectorial map layers with Django"
+name = "django-geojson"
+optional = false
+platform = "*"
+python-versions = "*"
+version = "2.11.0"
+
+[package.dependencies]
+Django = "*"
+six = "*"
+
+[[package]]
+category = "main"
+description = "This Django app allows you to export certain settings to your templates."
+name = "django-settings-export"
+optional = false
+platform = "*"
+python-versions = "*"
+version = "1.2.1"
+
+[package.dependencies]
+django = "*"
+
+[[package]]
+category = "main"
+description = "Store model history and view/revert changes from admin site."
+name = "django-simple-history"
+optional = false
+platform = "*"
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+version = "2.3.0"
+
+[[package]]
+category = "main"
+description = "Transparently use webpack with django"
+name = "django-webpack-loader"
+optional = false
+platform = "*"
+python-versions = "*"
+version = "0.6.0"
+
+[[package]]
+category = "main"
+description = "Tweak the form field rendering in templates, not in python-level form definitions."
+name = "django-widget-tweaks"
+optional = false
+platform = "*"
+python-versions = "*"
+version = "1.4.2"
+
+[[package]]
+category = "main"
+description = "A pure python-based utility to extract text and images from docx files."
+name = "docx2txt"
+optional = false
+platform = "UNKNOWN"
+python-versions = "*"
+version = "0.6"
+
+[[package]]
+category = "main"
+description = "Python client for Elasticsearch"
+name = "elasticsearch"
+optional = false
+platform = "*"
+python-versions = "*"
+version = "5.5.3"
+
+[package.dependencies]
+urllib3 = ">=1.21.1"
+
+[[package]]
+category = "main"
+description = "Python client for Elasticsearch"
+name = "elasticsearch-dsl"
+optional = false
+platform = "*"
+python-versions = "*"
+version = "5.4.0"
+
+[package.dependencies]
+elasticsearch = ">=5.0.0,<6.0.0"
+python-dateutil = "*"
+six = "*"
+
+[[package]]
+category = "main"
+description = "A simple framework for building complex web applications."
+name = "flask"
+optional = false
+platform = "any"
+python-versions = "*"
+version = "1.0.2"
+
+[package.dependencies]
+Jinja2 = ">=2.10"
+Werkzeug = ">=0.14"
+click = ">=5.1"
+itsdangerous = ">=0.24"
+
+[[package]]
+category = "main"
+description = ""
+name = "geoextract"
+optional = false
+platform = "*"
+python-versions = "*"
+version = "0.3.0"
+
+[package.dependencies]
+Flask = ">=0.12.1"
+nltk = ">=3.2.2"
+numpy = ">=1.11.0"
+pyahocorasick = ">=1.1.4"
+scipy = ">=0.17.0"
+six = ">=1.10.0"
+unidecode = ">=0.4.21"
+
+[package.source]
+reference = "0d184e264c8356d22580076d35f16866c8ce6ecc"
+type = "git"
+url = "https://github.com/meine-stadt-transparent/geoextract"
+[[package]]
+category = "main"
+description = "The geodesic routines from GeographicLib"
+name = "geographiclib"
+optional = false
+platform = "*"
+python-versions = "*"
+version = "1.49"
+
+[[package]]
+category = "main"
+description = "Python Geocoding Toolbox"
+name = "geopy"
+optional = false
+platform = "*"
+python-versions = "*"
+version = "1.16.0"
+
+[package.dependencies]
+geographiclib = ">=1.49,<2"
+
+[[package]]
+category = "main"
+description = "WSGI HTTP Server for UNIX"
+name = "gunicorn"
+optional = false
+platform = "*"
+python-versions = ">=2.6, !=3.0.*, !=3.1.*"
+version = "19.9.0"
+
+[[package]]
+category = "main"
+description = "Turn HTML into equivalent Markdown-structured text."
+name = "html2text"
+optional = false
+platform = "OS Independent"
+python-versions = "*"
+version = "2018.1.9"
+
+[[package]]
+category = "main"
+description = "iCalendar parser/generator"
+name = "icalendar"
+optional = false
+platform = "*"
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+version = "4.0.2"
+
+[package.dependencies]
+python-dateutil = "*"
+pytz = "*"
+
+[[package]]
+category = "main"
+description = "Internationalized Domain Names in Applications (IDNA)"
+name = "idna"
+optional = false
+platform = "*"
+python-versions = "*"
+version = "2.7"
+
+[[package]]
+category = "main"
+description = "Various helpers to pass trusted data to untrusted environments and back."
+name = "itsdangerous"
+optional = false
+platform = "UNKNOWN"
+python-versions = "*"
+version = "0.24"
+
+[[package]]
+category = "main"
+description = "A small but fast and easy to use stand-alone template engine written in pure python."
+name = "jinja2"
+optional = false
+platform = "*"
+python-versions = "*"
+version = "2.10"
+
+[package.dependencies]
+MarkupSafe = ">=0.23"
+
+[[package]]
+category = "main"
+description = "A reusable Django field that allows you to store validated JSON in your model."
+name = "jsonfield"
+optional = false
+platform = "*"
+python-versions = "*"
+version = "2.0.2"
+
+[package.dependencies]
+Django = ">=1.8.0"
+
+[[package]]
+category = "main"
+description = "Powerful and Pythonic XML processing library combining libxml2/libxslt with the ElementTree API."
+name = "lxml"
+optional = false
+platform = "*"
+python-versions = "*"
+version = "4.2.4"
+
+[[package]]
+category = "main"
+description = "Implements a XML/HTML/XHTML Markup safe string for Python"
+name = "markupsafe"
+optional = false
+platform = "UNKNOWN"
+python-versions = "*"
+version = "1.0"
+
+[[package]]
+category = "main"
+description = "Python interface to MySQL"
+name = "mysqlclient"
+optional = false
+platform = "ALL"
+python-versions = "*"
+version = "1.3.13"
+
+[[package]]
+category = "main"
+description = "Natural Language Toolkit"
+name = "nltk"
+optional = false
+platform = "*"
+python-versions = "*"
+version = "3.3"
+
+[[package]]
+category = "main"
+description = "NumPy: array processing for numbers, strings, records, and objects."
+name = "numpy"
+optional = false
+platform = "Windows"
+python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*"
+version = "1.15.1"
+
+[[package]]
+category = "main"
+description = "A generic, spec-compliant, thorough implementation of the OAuth request-signing logic"
+name = "oauthlib"
+optional = false
+platform = "any"
+python-versions = "*"
+version = "2.1.0"
+
+[[package]]
+category = "main"
+description = "Python Imaging Library (Fork)"
+name = "pillow"
+optional = false
+platform = "*"
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+version = "5.2.0"
+
+[[package]]
+category = "main"
+description = "Python interface to CMU Sphinxbase and Pocketsphinx libraries"
+name = "pocketsphinx"
+optional = false
+platform = "*"
+python-versions = "*"
+version = "0.1.3"
+
+[[package]]
+category = "main"
+description = "pyahocorasick is a fast and memory efficient library for exact or approximate multi-pattern string search. With the ahocorasick.Automaton class, you can find multiple key strings occurrences at once in some input text. You can use it as a plain dict-like Trie or convert a Trie to an automaton for efficient Aho-Corasick search. Implemented in C and tested on Python 2.7 and 3.4+. Works on Linux, Mac and Windows. BSD-3-clause license."
+name = "pyahocorasick"
+optional = false
+platform = "Linux"
+python-versions = "*"
+version = "1.1.8"
+
+[[package]]
+category = "main"
+description = "PDF toolkit"
+name = "pypdf2"
+optional = false
+platform = "UNKNOWN"
+python-versions = "*"
+version = "1.26.0"
+
+[[package]]
+category = "main"
+description = "Extensions to the standard Python datetime module"
+name = "python-dateutil"
+optional = false
+platform = "*"
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*"
+version = "2.7.3"
+
+[package.dependencies]
+six = ">=1.5"
+
+[[package]]
+category = "main"
+description = "OpenID support for servers and consumers."
+name = "python-openid"
+optional = false
+platform = "UNKNOWN"
+python-versions = "*"
+version = "2.2.5"
+
+[[package]]
+category = "main"
+description = "Generate and manipulate Open XML PowerPoint (.pptx) files"
+name = "python-pptx"
+optional = false
+platform = "*"
+python-versions = "*"
+version = "0.6.6"
+
+[package.dependencies]
+Pillow = ">=2.6.1"
+XlsxWriter = ">=0.5.7"
+lxml = ">=3.1.0"
+
+[[package]]
+category = "main"
+description = "A Python Slugify application that handles Unicode"
+name = "python-slugify"
+optional = false
+platform = "*"
+python-versions = "*"
+version = "1.2.6"
+
+[package.dependencies]
+Unidecode = ">=0.04.16"
+
+[[package]]
+category = "main"
+description = "World timezone definitions, modern and historical"
+name = "pytz"
+optional = false
+platform = "Independent"
+python-versions = "*"
+version = "2018.5"
+
+[[package]]
+category = "main"
+description = "Python HTTP for Humans."
+name = "requests"
+optional = false
+platform = "*"
+python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+version = "2.19.1"
+
+[package.dependencies]
+certifi = ">=2017.4.17"
+chardet = ">=3.0.2,<3.1.0"
+idna = ">=2.5,<2.8"
+urllib3 = ">=1.21.1,<1.24"
+
+[[package]]
+category = "main"
+description = "OAuthlib authentication support for Requests."
+name = "requests-oauthlib"
+optional = false
+platform = "*"
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+version = "1.0.0"
+
+[package.dependencies]
+oauthlib = ">=0.6.2"
+requests = ">=2.0.0"
+
+[[package]]
+category = "main"
+description = "SciPy: Scientific Library for Python"
+name = "scipy"
+optional = false
+platform = "Windows"
+python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*"
+version = "1.1.0"
+
+[package.dependencies]
+numpy = ">=1.8.2"
+
+[[package]]
+category = "main"
+description = "Python bindings for Selenium"
+name = "selenium"
+optional = false
+platform = "*"
+python-versions = "*"
+version = "3.8.0"
+
+[[package]]
+category = "main"
+description = "Python 2 and 3 compatibility utilities"
+name = "six"
+optional = false
+platform = "UNKNOWN"
+python-versions = "*"
+version = "1.10.0"
+
+[[package]]
+category = "main"
+description = "Library for performing speech recognition, with support for several engines and APIs, online and offline."
+name = "speechrecognition"
+optional = false
+platform = "*"
+python-versions = "*"
+version = "3.7.1"
+
+[[package]]
+category = "main"
+description = "browser abstraction for web acceptance testing"
+name = "splinter"
+optional = false
+platform = "*"
+python-versions = "*"
+version = "0.7.7"
+
+[package.dependencies]
+selenium = ">=3.4.3"
+
+[[package]]
+category = "main"
+description = "Non-validating SQL parser"
+name = "sqlparse"
+optional = false
+platform = "*"
+python-versions = "*"
+version = "0.2.4"
+
+[[package]]
+category = "main"
+description = ""
+name = "textract"
+optional = false
+platform = "*"
+python-versions = "*"
+version = "1.6.1"
+
+[package.dependencies]
+SpeechRecognition = "3.7.1"
+argcomplete = "1.8.2"
+beautifulsoup4 = "4.6.0"
+chardet = "3.0.4"
+docx2txt = "0.6"
+pocketsphinx = "0.1.3"
+python-pptx = "0.6.6"
+six = "1.10.0"
+xlrd = "1.0.0"
+
+[package.source]
+reference = "0776b86cd01fbad5b2518f75a659a1e5b614a5bd"
+type = "git"
+url = "https://github.com/meine-stadt-transparent/textract"
+[[package]]
+category = "main"
+description = "ASCII transliterations of Unicode text"
+name = "unidecode"
+optional = false
+platform = "*"
+python-versions = "*"
+version = "1.0.22"
+
+[[package]]
+category = "main"
+description = "HTTP library with thread-safe connection pooling, file post, and more."
+name = "urllib3"
+optional = false
+platform = "*"
+python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, <4"
+version = "1.23"
+
+[[package]]
+category = "main"
+description = "Ctypes-based simple MagickWand API binding for Python"
+name = "wand"
+optional = false
+platform = "UNKNOWN"
+python-versions = "*"
+version = "0.4.4"
+
+[[package]]
+category = "main"
+description = "The comprehensive WSGI web application library."
+name = "werkzeug"
+optional = false
+platform = "any"
+python-versions = "*"
+version = "0.14.1"
+
+[[package]]
+category = "main"
+description = "Library for developers to extract data from Microsoft Excel (tm) spreadsheet files"
+name = "xlrd"
+optional = false
+platform = "Any platform -- don't need Windows"
+python-versions = "*"
+version = "1.0.0"
+
+[[package]]
+category = "main"
+description = "A Python module for creating Excel XLSX files."
+name = "xlsxwriter"
+optional = false
+platform = "*"
+python-versions = "*"
+version = "1.1.0"
+
+[metadata]
+content-hash = "22162a04575d4859af6e719d86a7f92aa1be63a283b73a2e3bb1b1982b59a357"
+platform = "*"
+python-versions = "^3.7"
+
+[metadata.hashes]
+argcomplete = ["7a2ccde074eb6631232b2f91f8d8d5985d5bebf0e36b091113096e3a0385546b", "c2a0a88492c31a42dde41636fbd4c406cde78fe7fb938ab511b733bff6358782"]
+beautifulsoup4 = ["11a9a27b7d3bddc6d86f59fb76afb70e921a25ac2d6cc55b40d072bd68435a76", "7015e76bf32f1f574636c4288399a6de66ce08fb7b2457f628a8d70c0fbabb11", "808b6ac932dccb0a4126558f7dfdcf41710dd44a4ef497a0bb59a77f9f078e89"]
+certifi = ["376690d6f16d32f9d1fe8932551d80b23e9d393a8578c5633a2ed39a64861638", "456048c7e371c089d0a77a5212fb37a2c2dce1e24146e3b7e0261736aaeaa22a"]
+chardet = ["84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae", "fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"]
+click = ["29f99fc6125fbc931b758dc053b3114e55c77a6e4c6c3a2674a2dc986016381d", "f15516df478d5a56180fbf80e68f206010e6d160fc39fa508b65e035fd75130b"]
+django = ["8176ac7985fe6737ce3d6b2531b4a2453cb7c3377c9db00bacb2b3320f4a1311", "b18235d82426f09733d2de9910cee975cf52ff05e5f836681eb957d105a05a40"]
+django-allauth = ["02175aa1c2ddfd935a54011d1196d70c976647fc46f603f8b8758fc395b9d277"]
+django-anymail = ["a6ba5b5196fa469043f5bdc32b294ce2427c964e40c80b45c3a3cb91fc683d9f", "be245c774541ae73fbe3baabc686b03f6ae3fc0c058f7e9bf26e7da0a5584bab"]
+django-braces = ["a457d74ea29478123c0c4652272681b3cea0bf1232187fd9f9b6f1d97d32a890", "ba68e98b817c6f01d71d10849f359979617b3fe4cefb7f289adefddced092ddc"]
+django-csp = ["04c0ccd4e1339e8f6af48c55c3347dc996fde2d22d79e8bf2f6b7a920412e408", "096b634430d8ea81c3d9f216f87be890f3a975c17bb9a4631f6a1619ac09c91e"]
+django-debug-toolbar = ["4af2a4e1e932dadbda197b18585962d4fc20172b4e5a479490bc659fe998864d", "d9ea75659f76d8f1e3eb8f390b47fc5bad0908d949c34a8a3c4c87978eb40a0f"]
+django-elasticsearch-dsl = ["e09831997ffc6ca9061496146679f7dcedd9bf8a4c6883e67ab87c5ac0e08b8b"]
+django-environ = ["6c9d87660142608f63ec7d5ce5564c49b603ea8ff25da595fd6098f6dc82afde", "c57b3c11ec1f319d9474e3e5a79134f40174b17c7cc024bbb2fad84646b120c4"]
+django-geojson = ["9dd9fa8160088004ca27eecbb4bf1122a792f950af32df89b21d8864c088bb3d"]
+django-settings-export = ["fceeae49fc597f654c1217415d8e049fc81c930b7154f5d8f28c432db738ff79"]
+django-simple-history = ["426aead38ec1ee7911f8059dc6dcd9f3f375ffa15e11f5a4cd78222808040438", "7203979afd5a7acca09376b711abd58cd873e88f7892453abfc1322bc67a9603"]
+django-webpack-loader = ["60bab6b9a037a5346fad12d2a70a6bc046afb33154cf75ed640b93d3ebd5f520", "970b968c2a8975fb7eff56a3bab5d0d90d396740852d1e0c50c5cfe2b824199a"]
+django-widget-tweaks = ["a31c8a2b88af98dba6471db4722a416d1c643c87efecf9a7f17f983a2a553632", "f9961162c8ed272162e22e5877d29c7780476970441dce605118ef66da685e71"]
+docx2txt = ["24740c6574c5e483afc589206df4ab493b2495d4ae07f1ccb6125e5b8bfe1338"]
+elasticsearch = ["658380fd60bdaf746fef12958f0abc49063218ce93ee1ae4ca1fe6291c896433", "ae91b089f2f2b5b3daa04297949e5f805ab12d187218cb587273f472656fd250"]
+elasticsearch-dsl = ["197246ddd556b4b7d2738dfa9e4831068c9b5cb21706f6aca035136d42849109", "cbef6467085d7debc870bc450d996c7ba5b8822eb86a6033bba09134ffb01ba8"]
+flask = ["2271c0070dbcb5275fad4a82e29f23ab92682dc45f9dfbc22c02ba9b9322ce48", "a080b744b7e345ccfcbc77954861cb05b3c63786e93f2b3875e0913d44b43f05"]
+geoextract = []
+geographiclib = ["635da648fce80a57b81b28875d103dacf7deb12a3f5f7387ba7d39c51e096533"]
+geopy = ["76654405eb69b01a2b8d113ab2ae101513cbeeb1272b0a472a7050631dadefa0", "a70ff7d0fed8574384a033b46a0cd07ed7bf824901031da6e315f63e6d70394e"]
+gunicorn = ["aa8e0b40b4157b36a5df5e599f45c9c76d6af43845ba3b3b0efe2c70473c2471", "fa2662097c66f920f53f70621c6c58ca4a3c4d3434205e608e121b5b3b71f4f3"]
+html2text = ["490db40fe5b2cd79c461cf56be4d39eb8ca68191ae41ba3ba79f6cb05b7dd662", "627514fb30e7566b37be6900df26c2c78a030cc9e6211bda604d8181233bcdd4"]
+icalendar = ["2f7166b36ed52e7ab3f2c6aacabb4300095e10c3a6244a53e2f77410633989ae", "80362a9f3c2686b88791fdb78c063f33bd96451f7b1b12140c5aad2df81c008c"]
+idna = ["156a6814fb5ac1fc6850fb002e0852d56c0c8d2531923a51032d1b70760e186e", "684a38a6f903c1d71d6d5fac066b58d7768af4de2b832e426ec79c30daa94a16"]
+itsdangerous = ["cbb3fcf8d3e33df861709ecaf89d9e6629cff0a217bc2848f1b41cd30d360519"]
+jinja2 = ["74c935a1b8bb9a3947c50a54766a969d4846290e1e788ea44c1392163723c3bd", "f84be1bb0040caca4cea721fcbbbbd61f9be9464ca236387158b0feea01914a4"]
+jsonfield = ["a0a7fdee736ff049059409752b045281a225610fecbda9b9bd588ba976493c12", "beb1cd4850d6d6351c32daefcb826c01757744e9c863228a642f87a1a4acb834"]
+lxml = ["0cf1eca0652c4409e0655e04b840d6d85b7eb18718f5fba3862acad5500e3480", "10624ef1b468252309f269b13af4f837e3a82be366b5f3e49b0e83f1ad66205f", "1259e374da3a575615fe402e0966c5894bae3d2e229c2239ba4ebf2bb020c4b6", "26bb748af1ead0097eb8272b8a06f15a0015b8f312eef772a95f223a16e7de56", "27d0b13bcfcf2f6a5664e64fc3d684c76db1cdba5a5761795d154063559e0b59", "2b013fdabcbc21bc2770437099b921ec290235752b5baaac7a601f75094a378d", "2e469ea2c0b722b9b393187649e7d126c537a68512fc92a676fe86e57050c2a9", "37f7c2cdf513a0ea239c1609681880fb2f0073de0d2996e0ae9a7f0ef15d8b95", "68c6afc7a4411db2df28307e2493c945cb3d887e8f431b81811c1ea6ba087b8b", "73fe3452fc02c0b418914f842f897bdad0f1184368d8d9c315294ff7b94946f2", "7584d83d7315f641510e5f97f4d636ea225fd76e3f8aee965b2e8c93a8169b4d", "76e3ec6b26b1198dd5e6e20539d8360dcd3b224cd80cadba9307b790fda79161", "8288a889cbaa446e5fa168837456e63098b91953c89e5857968a5091b337cdca", "ad9e1fee284dec97b74cd88e925eca1575145598c974243cfb5e859f406adc32", "b360c3769cf0fd7d82577e40e37d4caf693f67744d0d61d11d66b5c31eaccf7a", "c4aaf320284a2713428163bae0e7df0db3b489237ab4830179210a12d56d3068", "c530274e43b0f376cd94e8e0a3e6ea28de1739ec4326689bdbf626e172d2e614", "ca4e79294fd0f3f9e0e5a4c309df84b5f2abc62349bfaf2aaf8965e5108ef8e2", "ce2dc5a104e885abbd48d0cc92ae74afa1d685ee65d6e3497067207d6a26e177", "d295cac30d3e13e82473081ea7df2a11352b5625cb54187fcd5a8be5d9ebf315", "d498338b39c4757ba88bdc705b3a0647d18554856cd2d394ac3bb919ac890c9d", "d537f8e613074805e17039e345edaa822534f66f07d315c89cff9824aa996d65", "df8ba3f52ef59a553b0e94593ea526c34faa4f531c1ab7f5ca7f392bc770c9e3", "e2553800d2d461a2dc329682d0a9068f238ec11d763e5454c61c4df7a0346ed2", "e2afbe403090f5893e254958d02875e0732975e73c4c0cdd33c1f009a61963ca", "e740efa625883f3c4de20c7e1411228d7ce2ab47b9e874a703f6681ec0558a30", "ec7864b62da0f5ae44973351247f2250a25b9b544fc6aff8bd6a75da1156cc70", "f26ddab491b10279b7e8e3fdcbaaaba3ab282fbaecfa48a19874dfc4d53b9d4f", "f6a16681f30918521066ddcc4ba79c1e033c9837dd94f78f5a9f6110e7572185", "f968623ac9b81a6253d4bbbe3f4d1e6be5f33707f397b566935783511bfa281a"]
+markupsafe = ["a6be69091dac236ea9c6bc7d012beab42010fa914c459791d627dad4910eb665"]
+mysqlclient = ["ff8ee1be84215e6c30a746b728c41eb0701a46ca76e343af445b35ce6250644f"]
+nltk = ["687cd9c09fcb68058436f9952964e758673c7baccb7a322470f8c1b284e33cee", "fe0eda251be65843be86d7de9abfbf7161732256f742e623b21243ec47bdb718"]
+numpy = ["1c362ad12dd09a43b348bb28dd2295dd9cdf77f41f0f45965e04ba97f525b864", "2156a06bd407918df4ac0122df6497a9c137432118f585e5b17d543e593d1587", "24e4149c38489b51fc774b1e1faa9103e82f73344d7a00ba66f6845ab4769f3f", "340ec1697d9bb3a9c464028af7a54245298502e91178bddb4c37626d36e197b7", "35db8d419345caa4eeaa65cd63f34a15208acd87530a30f0bc25fc84f55c8c80", "361370e9b7f5e44c41eee29f2bb5cb3b755abb4b038bce6d6cbe08db7ff9cb74", "36e8dcd1813ca92ce7e4299120cee6c03adad33d89b54862c1b1a100443ac399", "378378973546ecc1dfaf9e24c160d683dd04df871ecd2dcc86ce658ca20f92c0", "419e6faee16097124ee627ed31572c7e80a1070efa25260b78097cca240e219a", "4287104c24e6a09b9b418761a1e7b1bbde65105f110690ca46a23600a3c606b8", "549f3e9778b148a47f4fb4682955ed88057eb627c9fe5467f33507c536deda9d", "5e359e9c531075220785603e5966eef20ccae9b3b6b8a06fdfb66c084361ce92", "5ee7f3dbbdba0da75dec7e94bd7a2b10fe57a83e1b38e678200a6ad8e7b14fdc", "62d55e96ec7b117d3d5e618c15efcf769e70a6effaee5842857b64fb4883887a", "719b6789acb2bc86ea9b33a701d7c43dc2fc56d95107fd3c5b0a8230164d4dfb", "7a70f2b60d48828cba94a54a8776b61a9c2657a803d47f5785f8062e3a9c7c55", "7b9e37f194f8bcdca8e9e6af92e2cbad79e360542effc2dd6b98d63955d8d8a3", "83b8fc18261b70f45bece2d392537c93dc81eb6c539a16c9ac994c47fc79f09a", "9473ad28375710ab18378e72b59422399b27e957e9339c413bf00793b4b12df0", "95b085b253080e5d09f7826f5e27dce067bae813a132023a77b739614a29de6e", "98b86c62c08c2e5dc98a9c856d4a95329d11b1c6058cb9b5191d5ea6891acd09", "a3bd01d6d3ed3d7c06d7f9979ba5d68281f15383fafd53b81aa44b9191047cf8", "c81a6afc1d2531a9ada50b58f8c36197f8418ef3d0611d4c1d7af93fdcda764f", "ce75ed495a746e3e78cfa22a77096b3bff2eda995616cb7a542047f233091268", "dae8618c0bcbfcf6cf91350f8abcdd84158323711566a8c5892b5c7f832af76f", "df0b02c6705c5d1c25cc35c7b5d6b6f9b3b30833f9d178843397ae55ecc2eebb", "e3660744cda0d94b90141cdd0db9308b958a372cfeee8d7188fdf5ad9108ea82", "f2362d0ca3e16c37782c1054d7972b8ad2729169567e3f0f4e5dd3cdf85f188e"]
+oauthlib = ["ac35665a61c1685c56336bda97d5eefa246f1202618a1d6f34fccb1bdd404162", "d883b36b21a6ad813953803edfa563b1b579d79ca758fe950d1bc9e8b326025b"]
+pillow = ["00def5b638994f888d1058e4d17c86dec8e1113c3741a0a8a659039aec59a83a", "026449b64e559226cdb8e6d8c931b5965d8fc90ec18ebbb0baa04c5b36503c72", "03dbb224ee196ef30ed2156d41b579143e1efeb422974719a5392fc035e4f574", "03eb0e04f929c102ae24bc436bf1c0c60a4e63b07ebd388e84d8b219df3e6acd", "087b0551ce2d19b3f092f2b5f071a065f7379e748867d070b29999cc83db15e3", "091a0656688d85fd6e10f49a73fa3ab9b37dbfcb2151f5a3ab17f8b879f467ee", "0f3e2d0a9966161b7dfd06d147f901d72c3a88ea1a833359b92193b8e1f68e1c", "114398d0e073b93e1d7da5b5ab92ff4b83c0180625c8031911425e51f4365d2e", "1be66b9a89e367e7d20d6cae419794997921fe105090fafd86ef39e20a3baab2", "1c5e93c40d4ce8cb133d3b105a869be6fa767e703f6eb1003eb4b90583e08a59", "1e977a3ed998a599bda5021fb2c2889060617627d3ae228297a529a082a3cd5c", "22cf3406d135cfcc13ec6228ade774c8461e125c940e80455f500638429be273", "24adccf1e834f82718c7fc8e3ec1093738da95144b8b1e44c99d5fc7d3e9c554", "2a3e362c97a5e6a259ee9cd66553292a1f8928a5bdfa3622fdb1501570834612", "3518f9fc666cbc58a5c1f48a6a23e9e6ceef69665eab43cdad5144de9383e72c", "3709339f4619e8c9b00f53079e40b964f43c5af61fb89a923fe24437167298bb", "3832e26ecbc9d8a500821e3a1d3765bda99d04ae29ffbb2efba49f5f788dc934", "452d159024faf37cc080537df308e8fa0026076eb38eb75185d96ed9642bd6d7", "4fd1f0c2dc02aaec729d91c92cd85a2df0289d88e9f68d1e8faba750bb9c4786", "4fda62030f2c515b6e2e673c57caa55cb04026a81968f3128aae10fc28e5cc27", "5044d75a68b49ce36a813c82d8201384207112d5d81643937fc758c05302f05b", "522184556921512ec484cb93bd84e0bab915d0ac5a372d49571c241a7f73db62", "5914cff11f3e920626da48e564be6818831713a3087586302444b9c70e8552d9", "653d48fe46378f40e3c2b892be88d8440efbb2c9df78559da44c63ad5ecb4142", "6661a7908d68c4a133e03dac8178287aa20a99f841ea90beeb98a233ae3fd710", "6735a7e560df6f0deb78246a6fe056cf2ae392ba2dc060ea8a6f2535aec924f1", "6d26a475a19cb294225738f5c974b3a24599438a67a30ed2d25638f012668026", "791f07fe13937e65285f9ef30664ddf0e10a0230bdb236751fa0ca67725740dd", "79258a8df3e309a54c7ef2ef4a59bb8e28f7e4a8992a3ad17c24b1889ced44f3", "7d74c20b8f1c3e99d3f781d3b8ff5abfefdd7363d61e23bdeba9992ff32cc4b4", "81918afeafc16ba5d9d0d4e9445905f21aac969a4ebb6f2bff4b9886da100f4b", "8194d913ca1f459377c8a4ed8f9b7ad750068b8e0e3f3f9c6963fcc87a84515f", "84d5d31200b11b3c76fab853b89ac898bf2d05c8b3da07c1fcc23feb06359d6e", "989981db57abffb52026b114c9a1f114c7142860a6d30a352d28f8cbf186500b", "a3d7511d3fad1618a82299aab71a5fceee5c015653a77ffea75ced9ef917e71a", "a4a6ac01b8c2f9d2d83719f193e6dea493e18445ce5bfd743d739174daa974d9", "acb90eb6c7ed6526551a78211d84c81e33082a35642ff5fe57489abc14e6bf6e", "b3ef168d4d6fd4fa6685aef7c91400f59f7ab1c0da734541f7031699741fb23f", "c1c5792b6e74bbf2af0f8e892272c2a6c48efa895903211f11b8342e03129fea", "c5dcb5a56aebb8a8f2585042b2f5c496d7624f0bcfe248f0cc33ceb2fd8d39e7", "d16f90810106822833a19bdb24c7cb766959acf791ca0edf5edfec674d55c8ee", "dcdc9cd9880027688007ff8f7c8e7ae6f24e81fae33bfd18d1e691e7bda4855f", "e2807aad4565d8de15391a9548f97818a14ef32624015c7bf3095171e314445e", "e2bed4a04e2ca1050bb5f00865cf2f83c0b92fd62454d9244f690fcd842e27a4", "e87a527c06319428007e8c30511e1f0ce035cb7f14bb4793b003ed532c3b9333", "ebcfc33a6c34984086451e230253bc33727bd17b4cdc4b39ec03032c3a6fc9e9", "f63e420180cbe22ff6e32558b612e75f50616fc111c5e095a4631946c782e109", "f7717eb360d40e7598c30cc44b33d98f79c468d9279379b66c1e28c568e0bf47", "f8582e1ab155302ea9ef1235441a0214919f4f79c4c7c21833ce9eec58181781", "f8b3d413c5a8f84b12cd4c5df1d8e211777c9852c6be3ee9c094b626644d3eab"]
+pocketsphinx = ["019d2a2971f19aac3e319f2536fd1ff13b14ed9c7fbf9bc3440cb07fe261e5a4", "21d0cfdeb78910b22562504c7d9a53868f64b9040888cc193c03198a849e5dae", "2b06fea365b55a40a0e51510b1b62a1575f264a38516ad20b940c133d569f6ef", "2f5ec0f812c3e346efd8143427fe1064b3fdc10038396caae0aca7afcba782e1", "42c82f117009a7355f281932a5fe6bee1f68a432631712241c60d207ef267931", "4dc0af673eb6d0523237ea66f2f72f9be38021c3e702e07d67718afd02220cac", "59f6de8ec032dccf059e0c5c9f1a21df553b9cfb6f4d5ebcfe580634c849f376", "6701ef8b107605771b52d60a592b65bae093cf533c3c070bd2ddb2807c609fde", "7fc0d6de2c64448ff9370249723b9319c75ad2f524f0d57e30f80bf521fa26f1", "919503baba39604d6f1b8017a8fc239c41f77c7646748a0cc077001579a0bade", "9a254518c4ff7f57aec7bdc86792d391622768bbc348bb0e0ebb1cbcf55184da", "9cb4b05b16b805c3460a323304b907f3a3609bb3e969ed09e361273f6ed16681", "9cee94eb0e861f7bba0bd9081176cd48bb49909fabb01330c2d1d1c1b336e7b1", "9f932d7a6e2ec04ea8f0b019537fa0c92e702a226a02007223c55a46606c9568", "a57ab9c122540cd8b2d6a9658cbfa05197eb013120a9b91b11a49f96ce4f2a8c", "a65ea9e5c9218b529de7d5560d302bc95aa21741fd9564896fdf362e2cd0e82d", "ac125aadefc85ab78706a4d18ae66c3dcf89eb9e2a0cbd88c7a6086df420346d", "ba144654675157c3c5ab890c86cfefbd495790e1ad9f8be97f64738bb0e7e785", "c1951834ebc1c0bad31bb0bbb8337921e6333b63be1582f6fe2c14132cfba162", "cb3a4c5427de4975269f9d6fec975fc958431e3382f31921830fda08a8b795a6", "ccdc5fb5591649cd0edcdde541bc813b5f74bf5dd04872b937e551732eaa6847", "da40cac571b9f2113bd0446b7fcb9a0e6d5e190e283d16864680fa83d45e2383", "e05e0ed601916e78d4854b23ce3699cd287208d63143b0c38bc060dbe4ccbcec", "f6bfa8e9a08026c46061364f59e9af8b0f4049142d4f155d9f07229d9b2d8281", "fdbf33d926aece1c56fc7772fe7763f371eb8b0029ed85b498558aba15a8eb21"]
+pyahocorasick = ["3d584e7836ca7b066f99d7fdb384dc6ef7af211b2b139baedbd960c7c279bb7f"]
+pypdf2 = ["e28f902f2f0a1603ea95ebe21dff311ef09be3d0f0ef29a3e44a932729564385"]
+python-dateutil = ["1adb80e7a782c12e52ef9a8182bebeb73f1d7e24e374397af06fb4956c8dc5c0", "e27001de32f627c22380a688bcc43ce83504a7bc5da472209b4c70f02829f0b8"]
+python-openid = ["92c51c3ecec846cbec4aeff11f9ff47303d4a63f93b0e6ac0ec02a091fed70ef", "c2d133e47e0a7705c9272eef00d7a09c174f5bf17a127fed8e2c6499556cc782"]
+python-pptx = ["b7508d6ab2954854b6efeb2ffc2653ff0e8185fb314df6c8673c534b0caeed50"]
+python-slugify = ["7723daf30996db26573176bddcdf5fcb98f66dc70df05c9cb29f2c79b8193245"]
+pytz = ["a061aa0a9e06881eb8b3b2b43f05b9439d6583c206d0a6c340ff72a7b6669053", "ffb9ef1de172603304d9d2819af6f5ece76f2e85ec10692a524dd876e72bf277"]
+requests = ["63b52e3c866428a224f97cab011de738c36aec0185aa91cfacd418b5d58911d1", "ec22d826a36ed72a7358ff3fe56cbd4ba69dd7a6718ffd450ff0e9df7a47ce6a"]
+requests-oauthlib = ["8886bfec5ad7afb391ed5443b1f697c6f4ae98d0e5620839d8b4499c032ada3f", "e21232e2465808c0e892e0e4dbb8c2faafec16ac6dc067dd546e9b466f3deac8", "fe3282f48fb134ee0035712159f5429215459407f6d5484013343031ff1a400d"]
+scipy = ["0611ee97296265af4a21164a5323f8c1b4e8e15c582d3dfa7610825900136bb7", "08237eda23fd8e4e54838258b124f1cd141379a5f281b0a234ca99b38918c07a", "0e645dbfc03f279e1946cf07c9c754c2a1859cb4a41c5f70b25f6b3a586b6dbd", "0e9bb7efe5f051ea7212555b290e784b82f21ffd0f655405ac4f87e288b730b3", "108c16640849e5827e7d51023efb3bd79244098c3f21e4897a1007720cb7ce37", "340ef70f5b0f4e2b4b43c8c8061165911bc6b2ad16f8de85d9774545e2c47463", "3ad73dfc6f82e494195144bd3a129c7241e761179b7cb5c07b9a0ede99c686f3", "3b243c77a822cd034dad53058d7c2abf80062aa6f4a32e9799c95d6391558631", "404a00314e85eca9d46b80929571b938e97a143b4f2ddc2b2b3c91a4c4ead9c5", "423b3ff76957d29d1cce1bc0d62ebaf9a3fdfaf62344e3fdec14619bb7b5ad3a", "42d9149a2fff7affdd352d157fa5717033767857c11bd55aa4a519a44343dfef", "625f25a6b7d795e8830cb70439453c9f163e6870e710ec99eba5722775b318f3", "698c6409da58686f2df3d6f815491fd5b4c2de6817a45379517c92366eea208f", "729f8f8363d32cebcb946de278324ab43d28096f36593be6281ca1ee86ce6559", "8190770146a4c8ed5d330d5b5ad1c76251c63349d25c96b3094875b930c44692", "878352408424dffaa695ffedf2f9f92844e116686923ed9aa8626fc30d32cfd1", "8b984f0821577d889f3c7ca8445564175fb4ac7c7f9659b7c60bef95b2b70e76", "8f841bbc21d3dad2111a94c490fb0a591b8612ffea86b8e5571746ae76a3deac", "c22b27371b3866c92796e5d7907e914f0e58a36d3222c5d436ddd3f0e354227a", "d0cdd5658b49a722783b8b4f61a6f1f9c75042d0e29a30ccb6cacc9b25f6d9e2", "d40dc7f494b06dcee0d303e51a00451b2da6119acbeaccf8369f2d29e28917ac", "d8491d4784aceb1f100ddb8e31239c54e4afab8d607928a9f7ef2469ec35ae01", "dfc5080c38dde3f43d8fbb9c0539a7839683475226cf83e4b24363b227dfe552", "e24e22c8d98d3c704bb3410bce9b69e122a8de487ad3dbfe9985d154e5c03a40", "e7a01e53163818d56eabddcafdc2090e9daba178aad05516b20c6591c4811020", "ee677635393414930541a096fc8e61634304bb0153e4e02b75685b11eba14cae", "f0521af1b722265d824d6ad055acfe9bd3341765735c44b5a4d0069e189a0f40", "f25c281f12c0da726c6ed00535ca5d1622ec755c30a3f8eafef26cf43fede694"]
+selenium = ["3af07d7a4b5d523540fa4f32902b9dec15e0379862406aef974729f42411053d", "af448c15b3225056cd406b435cda10bfcee250460a4811e4fd8b21be9f61626c"]
+six = ["0ff78c403d9bccf5a425a6d31a12aa6b47f1c21ca4dc2573a7e2f32a97335eb1", "105f8d68616f8248e24bf0e9372ef04d3cc10104f1980f54d57b2ce73a5ad56a"]
+speechrecognition = ["fe4f5785e54e4b07852f00128f6219817cec7237c57194cf73608cbea327f7ad"]
+splinter = ["71a83ef32cd976f3fb80a190d3c439a6dd82c347bcd0feb068d7d48e14aee269", "f97119f84d339067169451d56043f37f6b0a504a17a7ac6e48c91c012be72af6"]
+sqlparse = ["ce028444cfab83be538752a2ffdb56bc417b7784ff35bb9a3062413717807dec", "d9cf190f51cbb26da0412247dfe4fb5f4098edb73db84e02f9fc21fdca31fed4"]
+textract = []
+unidecode = ["72f49d3729f3d8f5799f710b97c1451c5163102e76d64d20e170aedbbd923582", "8c33dd588e0c9bc22a76eaa0c715a5434851f726131bd44a6c26471746efabf5"]
+urllib3 = ["a68ac5e15e76e7e5dd2b8f94007233e01effe3e50e8daddf69acfd81cb686baf", "b5725a0bd4ba422ab0e66e89e030c806576753ea3ee08554382c14e685d117b5"]
+wand = ["28e0454c9d16d69c5d5034918d96320d8f9f1377b4fdaf4944eec2f938c74704", "fb50d0ad4cad995f0b59b13f76bced22682ab80b4299084a2c3c535b225850c9"]
+werkzeug = ["c3fd7a7d41976d9f44db327260e263132466836cef6f91512889ed60ad26557c", "d5da73735293558eb1651ee2fddc4d0dedcfa06538b8813a2e20011583c9e49b"]
+xlrd = ["05f55eb39a68f1c3d336de186aeb90c98ea5add722813738d8ae8b97819c5924", "0ff87dd5d50425084f7219cb6f86bb3eb5aa29063f53d50bf270ed007e941069"]
+xlsxwriter = ["18716ac3d8cd1f8c73af2a674df954bf4c1ae7a8b5944e1d6ca66815ece9518e", "b2c7cbe246d1e1d113b4d014a71d1d9bb258f28625512f8df290352d1685be13"]
diff --git a/uv/spec/fixtures/poetry_locks/git_dependency.lock b/uv/spec/fixtures/poetry_locks/git_dependency.lock
new file mode 100644
index 00000000000..b03b7137390
--- /dev/null
+++ b/uv/spec/fixtures/poetry_locks/git_dependency.lock
@@ -0,0 +1,197 @@
+# This file is automatically @generated by Poetry 1.6.1 and should not be changed by hand.
+
+[[package]]
+name = "atomicwrites"
+version = "1.4.1"
+description = "Atomic file writes."
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+files = [
+ {file = "atomicwrites-1.4.1.tar.gz", hash = "sha256:81b2c9071a49367a7f770170e5eec8cb66567cfbbc8c73d20ce5ca4a8d71cf11"},
+]
+
+[[package]]
+name = "attrs"
+version = "23.1.0"
+description = "Classes Without Boilerplate"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "attrs-23.1.0-py3-none-any.whl", hash = "sha256:1f28b4522cdc2fb4256ac1a020c78acf9cba2c6b461ccd2c126f3aa8e8335d04"},
+ {file = "attrs-23.1.0.tar.gz", hash = "sha256:6279836d581513a26f1bf235f9acd333bc9115683f14f7e8fae46c98fc50e015"},
+]
+
+[package.dependencies]
+importlib-metadata = {version = "*", markers = "python_version < \"3.8\""}
+
+[package.extras]
+cov = ["attrs[tests]", "coverage[toml] (>=5.3)"]
+dev = ["attrs[docs,tests]", "pre-commit"]
+docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope-interface"]
+tests = ["attrs[tests-no-zope]", "zope-interface"]
+tests-no-zope = ["cloudpickle", "hypothesis", "mypy (>=1.1.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"]
+
+[[package]]
+name = "colorama"
+version = "0.4.6"
+description = "Cross-platform colored terminal text."
+optional = false
+python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
+files = [
+ {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"},
+ {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
+]
+
+[[package]]
+name = "importlib-metadata"
+version = "6.7.0"
+description = "Read metadata from Python packages"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "importlib_metadata-6.7.0-py3-none-any.whl", hash = "sha256:cb52082e659e97afc5dac71e79de97d8681de3aa07ff18578330904a9d18e5b5"},
+ {file = "importlib_metadata-6.7.0.tar.gz", hash = "sha256:1aaf550d4f73e5d6783e7acb77aec43d49da8017410afae93822cc9cca98c4d4"},
+]
+
+[package.dependencies]
+typing-extensions = {version = ">=3.6.4", markers = "python_version < \"3.8\""}
+zipp = ">=0.5"
+
+[package.extras]
+docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"]
+perf = ["ipython"]
+testing = ["flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)", "pytest-ruff"]
+
+[[package]]
+name = "more-itertools"
+version = "9.1.0"
+description = "More routines for operating on iterables, beyond itertools"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "more-itertools-9.1.0.tar.gz", hash = "sha256:cabaa341ad0389ea83c17a94566a53ae4c9d07349861ecb14dc6d0345cf9ac5d"},
+ {file = "more_itertools-9.1.0-py3-none-any.whl", hash = "sha256:d2bc7f02446e86a68911e58ded76d6561eea00cddfb2a91e7019bbb586c799f3"},
+]
+
+[[package]]
+name = "pluggy"
+version = "1.2.0"
+description = "plugin and hook calling mechanisms for python"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "pluggy-1.2.0-py3-none-any.whl", hash = "sha256:c2fd55a7d7a3863cba1a013e4e2414658b1d07b6bc57b3919e0c63c9abb99849"},
+ {file = "pluggy-1.2.0.tar.gz", hash = "sha256:d12f0c4b579b15f5e054301bb226ee85eeeba08ffec228092f8defbaa3a4c4b3"},
+]
+
+[package.dependencies]
+importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""}
+
+[package.extras]
+dev = ["pre-commit", "tox"]
+testing = ["pytest", "pytest-benchmark"]
+
+[[package]]
+name = "py"
+version = "1.11.0"
+description = "library with cross-python path, ini-parsing, io, code, log facilities"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
+files = [
+ {file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"},
+ {file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"},
+]
+
+[[package]]
+name = "pytest"
+version = "3.7.4"
+description = "pytest: simple powerful testing with Python"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+files = [
+ {file = "pytest-3.7.4-py2.py3-none-any.whl", hash = "sha256:ad0c7db7b5d4081631e0155f5c61b80ad76ce148551aaafe3a718d65a7508b18"},
+ {file = "pytest-3.7.4.tar.gz", hash = "sha256:2d7c49e931316cc7d1638a3e5f54f5d7b4e5225972b3c9838f3584788d27f349"},
+]
+
+[package.dependencies]
+atomicwrites = ">=1.0"
+attrs = ">=17.4.0"
+colorama = {version = "*", markers = "sys_platform == \"win32\""}
+more-itertools = ">=4.0.0"
+pluggy = ">=0.7"
+py = ">=1.5.0"
+setuptools = "*"
+six = ">=1.10.0"
+
+[[package]]
+name = "setuptools"
+version = "68.0.0"
+description = "Easily download, build, install, upgrade, and uninstall Python packages"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "setuptools-68.0.0-py3-none-any.whl", hash = "sha256:11e52c67415a381d10d6b462ced9cfb97066179f0e871399e006c4ab101fc85f"},
+ {file = "setuptools-68.0.0.tar.gz", hash = "sha256:baf1fdb41c6da4cd2eae722e135500da913332ab3f2f5c7d33af9b492acb5235"},
+]
+
+[package.extras]
+docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-hoverxref (<2)", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (==0.8.3)", "sphinx-reredirects", "sphinxcontrib-towncrier"]
+testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pip-run (>=8.8)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"]
+testing-integration = ["build[virtualenv]", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"]
+
+[[package]]
+name = "six"
+version = "1.16.0"
+description = "Python 2 and 3 compatibility utilities"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*"
+files = [
+ {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"},
+ {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"},
+]
+
+[[package]]
+name = "toml"
+version = "0.10.2"
+description = "Python Library for Tom's Obvious, Minimal Language"
+optional = false
+python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
+files = []
+develop = false
+
+[package.source]
+type = "git"
+url = "https://github.com/uiri/toml.git"
+reference = "master"
+resolved_reference = "5706d3155f4da8f3b84875f80bfe0dfc6565f61f"
+
+[[package]]
+name = "typing-extensions"
+version = "4.7.1"
+description = "Backported and Experimental Type Hints for Python 3.7+"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "typing_extensions-4.7.1-py3-none-any.whl", hash = "sha256:440d5dd3af93b060174bf433bccd69b0babc3b15b1a8dca43789fd7f61514b36"},
+ {file = "typing_extensions-4.7.1.tar.gz", hash = "sha256:b75ddc264f0ba5615db7ba217daeb99701ad295353c45f9e95963337ceeeffb2"},
+]
+
+[[package]]
+name = "zipp"
+version = "3.15.0"
+description = "Backport of pathlib-compatible object wrapper for zip files"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "zipp-3.15.0-py3-none-any.whl", hash = "sha256:48904fc76a60e542af151aded95726c1a5c34ed43ab4134b597665c86d7ad556"},
+ {file = "zipp-3.15.0.tar.gz", hash = "sha256:112929ad649da941c23de50f356a2b5570c954b65150642bccdd66bf194d224b"},
+]
+
+[package.extras]
+docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"]
+testing = ["big-O", "flake8 (<5)", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)"]
+
+[metadata]
+lock-version = "2.0"
+python-versions = "^3.7"
+content-hash = "28fdfcbc2cc134e28603043559a0a63bc6d601f115626bcef1d57a6e3e6115d1"
diff --git a/uv/spec/fixtures/poetry_locks/git_dependency_in_a_subdirectory.lock b/uv/spec/fixtures/poetry_locks/git_dependency_in_a_subdirectory.lock
new file mode 100644
index 00000000000..52d74627753
--- /dev/null
+++ b/uv/spec/fixtures/poetry_locks/git_dependency_in_a_subdirectory.lock
@@ -0,0 +1,146 @@
+# This file is automatically @generated by Poetry 1.6.1 and should not be changed by hand.
+
+[[package]]
+name = "dependabot-subdir-lib"
+version = "1.2.0"
+description = "Testing subdir functionality for dependabot"
+optional = false
+python-versions = ">=3"
+files = []
+develop = false
+
+[package.dependencies]
+Jinja2 = "3.0.3"
+MarkupSafe = "2.1.3"
+protobuf = "4.23.2"
+validate-email = "1.3"
+
+[package.source]
+type = "git"
+url = "https://github.com/sysradium/dependabot-subdir-lib.git"
+reference = "v0.0.1"
+resolved_reference = "e4cd6d2890319efdb619334a50668fc86e27dae4"
+subdirectory = "python"
+
+[[package]]
+name = "jinja2"
+version = "3.0.3"
+description = "A very fast and expressive template engine."
+optional = false
+python-versions = ">=3.6"
+files = [
+ {file = "Jinja2-3.0.3-py3-none-any.whl", hash = "sha256:077ce6014f7b40d03b47d1f1ca4b0fc8328a692bd284016f806ed0eaca390ad8"},
+ {file = "Jinja2-3.0.3.tar.gz", hash = "sha256:611bb273cd68f3b993fabdc4064fc858c5b47a973cb5aa7999ec1ba405c87cd7"},
+]
+
+[package.dependencies]
+MarkupSafe = ">=2.0"
+
+[package.extras]
+i18n = ["Babel (>=2.7)"]
+
+[[package]]
+name = "markupsafe"
+version = "2.1.3"
+description = "Safely add untrusted strings to HTML/XML markup."
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "MarkupSafe-2.1.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:cd0f502fe016460680cd20aaa5a76d241d6f35a1c3350c474bac1273803893fa"},
+ {file = "MarkupSafe-2.1.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e09031c87a1e51556fdcb46e5bd4f59dfb743061cf93c4d6831bf894f125eb57"},
+ {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:68e78619a61ecf91e76aa3e6e8e33fc4894a2bebe93410754bd28fce0a8a4f9f"},
+ {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:65c1a9bcdadc6c28eecee2c119465aebff8f7a584dd719facdd9e825ec61ab52"},
+ {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:525808b8019e36eb524b8c68acdd63a37e75714eac50e988180b169d64480a00"},
+ {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:962f82a3086483f5e5f64dbad880d31038b698494799b097bc59c2edf392fce6"},
+ {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:aa7bd130efab1c280bed0f45501b7c8795f9fdbeb02e965371bbef3523627779"},
+ {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c9c804664ebe8f83a211cace637506669e7890fec1b4195b505c214e50dd4eb7"},
+ {file = "MarkupSafe-2.1.3-cp310-cp310-win32.whl", hash = "sha256:10bbfe99883db80bdbaff2dcf681dfc6533a614f700da1287707e8a5d78a8431"},
+ {file = "MarkupSafe-2.1.3-cp310-cp310-win_amd64.whl", hash = "sha256:1577735524cdad32f9f694208aa75e422adba74f1baee7551620e43a3141f559"},
+ {file = "MarkupSafe-2.1.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ad9e82fb8f09ade1c3e1b996a6337afac2b8b9e365f926f5a61aacc71adc5b3c"},
+ {file = "MarkupSafe-2.1.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3c0fae6c3be832a0a0473ac912810b2877c8cb9d76ca48de1ed31e1c68386575"},
+ {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b076b6226fb84157e3f7c971a47ff3a679d837cf338547532ab866c57930dbee"},
+ {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bfce63a9e7834b12b87c64d6b155fdd9b3b96191b6bd334bf37db7ff1fe457f2"},
+ {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:338ae27d6b8745585f87218a3f23f1512dbf52c26c28e322dbe54bcede54ccb9"},
+ {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e4dd52d80b8c83fdce44e12478ad2e85c64ea965e75d66dbeafb0a3e77308fcc"},
+ {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:df0be2b576a7abbf737b1575f048c23fb1d769f267ec4358296f31c2479db8f9"},
+ {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5bbe06f8eeafd38e5d0a4894ffec89378b6c6a625ff57e3028921f8ff59318ac"},
+ {file = "MarkupSafe-2.1.3-cp311-cp311-win32.whl", hash = "sha256:dd15ff04ffd7e05ffcb7fe79f1b98041b8ea30ae9234aed2a9168b5797c3effb"},
+ {file = "MarkupSafe-2.1.3-cp311-cp311-win_amd64.whl", hash = "sha256:134da1eca9ec0ae528110ccc9e48041e0828d79f24121a1a146161103c76e686"},
+ {file = "MarkupSafe-2.1.3-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:f698de3fd0c4e6972b92290a45bd9b1536bffe8c6759c62471efaa8acb4c37bc"},
+ {file = "MarkupSafe-2.1.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:aa57bd9cf8ae831a362185ee444e15a93ecb2e344c8e52e4d721ea3ab6ef1823"},
+ {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ffcc3f7c66b5f5b7931a5aa68fc9cecc51e685ef90282f4a82f0f5e9b704ad11"},
+ {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47d4f1c5f80fc62fdd7777d0d40a2e9dda0a05883ab11374334f6c4de38adffd"},
+ {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1f67c7038d560d92149c060157d623c542173016c4babc0c1913cca0564b9939"},
+ {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:9aad3c1755095ce347e26488214ef77e0485a3c34a50c5a5e2471dff60b9dd9c"},
+ {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:14ff806850827afd6b07a5f32bd917fb7f45b046ba40c57abdb636674a8b559c"},
+ {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8f9293864fe09b8149f0cc42ce56e3f0e54de883a9de90cd427f191c346eb2e1"},
+ {file = "MarkupSafe-2.1.3-cp312-cp312-win32.whl", hash = "sha256:715d3562f79d540f251b99ebd6d8baa547118974341db04f5ad06d5ea3eb8007"},
+ {file = "MarkupSafe-2.1.3-cp312-cp312-win_amd64.whl", hash = "sha256:1b8dd8c3fd14349433c79fa8abeb573a55fc0fdd769133baac1f5e07abf54aeb"},
+ {file = "MarkupSafe-2.1.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8e254ae696c88d98da6555f5ace2279cf7cd5b3f52be2b5cf97feafe883b58d2"},
+ {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb0932dc158471523c9637e807d9bfb93e06a95cbf010f1a38b98623b929ef2b"},
+ {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9402b03f1a1b4dc4c19845e5c749e3ab82d5078d16a2a4c2cd2df62d57bb0707"},
+ {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca379055a47383d02a5400cb0d110cef0a776fc644cda797db0c5696cfd7e18e"},
+ {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:b7ff0f54cb4ff66dd38bebd335a38e2c22c41a8ee45aa608efc890ac3e3931bc"},
+ {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:c011a4149cfbcf9f03994ec2edffcb8b1dc2d2aede7ca243746df97a5d41ce48"},
+ {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:56d9f2ecac662ca1611d183feb03a3fa4406469dafe241673d521dd5ae92a155"},
+ {file = "MarkupSafe-2.1.3-cp37-cp37m-win32.whl", hash = "sha256:8758846a7e80910096950b67071243da3e5a20ed2546e6392603c096778d48e0"},
+ {file = "MarkupSafe-2.1.3-cp37-cp37m-win_amd64.whl", hash = "sha256:787003c0ddb00500e49a10f2844fac87aa6ce977b90b0feaaf9de23c22508b24"},
+ {file = "MarkupSafe-2.1.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:2ef12179d3a291be237280175b542c07a36e7f60718296278d8593d21ca937d4"},
+ {file = "MarkupSafe-2.1.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2c1b19b3aaacc6e57b7e25710ff571c24d6c3613a45e905b1fde04d691b98ee0"},
+ {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8afafd99945ead6e075b973fefa56379c5b5c53fd8937dad92c662da5d8fd5ee"},
+ {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8c41976a29d078bb235fea9b2ecd3da465df42a562910f9022f1a03107bd02be"},
+ {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d080e0a5eb2529460b30190fcfcc4199bd7f827663f858a226a81bc27beaa97e"},
+ {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:69c0f17e9f5a7afdf2cc9fb2d1ce6aabdb3bafb7f38017c0b77862bcec2bbad8"},
+ {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:504b320cd4b7eff6f968eddf81127112db685e81f7e36e75f9f84f0df46041c3"},
+ {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:42de32b22b6b804f42c5d98be4f7e5e977ecdd9ee9b660fda1a3edf03b11792d"},
+ {file = "MarkupSafe-2.1.3-cp38-cp38-win32.whl", hash = "sha256:ceb01949af7121f9fc39f7d27f91be8546f3fb112c608bc4029aef0bab86a2a5"},
+ {file = "MarkupSafe-2.1.3-cp38-cp38-win_amd64.whl", hash = "sha256:1b40069d487e7edb2676d3fbdb2b0829ffa2cd63a2ec26c4938b2d34391b4ecc"},
+ {file = "MarkupSafe-2.1.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:8023faf4e01efadfa183e863fefde0046de576c6f14659e8782065bcece22198"},
+ {file = "MarkupSafe-2.1.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6b2b56950d93e41f33b4223ead100ea0fe11f8e6ee5f641eb753ce4b77a7042b"},
+ {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9dcdfd0eaf283af041973bff14a2e143b8bd64e069f4c383416ecd79a81aab58"},
+ {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:05fb21170423db021895e1ea1e1f3ab3adb85d1c2333cbc2310f2a26bc77272e"},
+ {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:282c2cb35b5b673bbcadb33a585408104df04f14b2d9b01d4c345a3b92861c2c"},
+ {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ab4a0df41e7c16a1392727727e7998a467472d0ad65f3ad5e6e765015df08636"},
+ {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7ef3cb2ebbf91e330e3bb937efada0edd9003683db6b57bb108c4001f37a02ea"},
+ {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:0a4e4a1aff6c7ac4cd55792abf96c915634c2b97e3cc1c7129578aa68ebd754e"},
+ {file = "MarkupSafe-2.1.3-cp39-cp39-win32.whl", hash = "sha256:fec21693218efe39aa7f8599346e90c705afa52c5b31ae019b2e57e8f6542bb2"},
+ {file = "MarkupSafe-2.1.3-cp39-cp39-win_amd64.whl", hash = "sha256:3fd4abcb888d15a94f32b75d8fd18ee162ca0c064f35b11134be77050296d6ba"},
+ {file = "MarkupSafe-2.1.3.tar.gz", hash = "sha256:af598ed32d6ae86f1b747b82783958b1a4ab8f617b06fe68795c7f026abbdcad"},
+]
+
+[[package]]
+name = "protobuf"
+version = "4.23.2"
+description = ""
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "protobuf-4.23.2-cp310-abi3-win32.whl", hash = "sha256:384dd44cb4c43f2ccddd3645389a23ae61aeb8cfa15ca3a0f60e7c3ea09b28b3"},
+ {file = "protobuf-4.23.2-cp310-abi3-win_amd64.whl", hash = "sha256:09310bce43353b46d73ba7e3bca78273b9bc50349509b9698e64d288c6372c2a"},
+ {file = "protobuf-4.23.2-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:b2cfab63a230b39ae603834718db74ac11e52bccaaf19bf20f5cce1a84cf76df"},
+ {file = "protobuf-4.23.2-cp37-abi3-manylinux2014_aarch64.whl", hash = "sha256:c52cfcbfba8eb791255edd675c1fe6056f723bf832fa67f0442218f8817c076e"},
+ {file = "protobuf-4.23.2-cp37-abi3-manylinux2014_x86_64.whl", hash = "sha256:86df87016d290143c7ce3be3ad52d055714ebaebb57cc659c387e76cfacd81aa"},
+ {file = "protobuf-4.23.2-cp37-cp37m-win32.whl", hash = "sha256:281342ea5eb631c86697e1e048cb7e73b8a4e85f3299a128c116f05f5c668f8f"},
+ {file = "protobuf-4.23.2-cp37-cp37m-win_amd64.whl", hash = "sha256:ce744938406de1e64b91410f473736e815f28c3b71201302612a68bf01517fea"},
+ {file = "protobuf-4.23.2-cp38-cp38-win32.whl", hash = "sha256:6c081863c379bb1741be8f8193e893511312b1d7329b4a75445d1ea9955be69e"},
+ {file = "protobuf-4.23.2-cp38-cp38-win_amd64.whl", hash = "sha256:25e3370eda26469b58b602e29dff069cfaae8eaa0ef4550039cc5ef8dc004511"},
+ {file = "protobuf-4.23.2-cp39-cp39-win32.whl", hash = "sha256:efabbbbac1ab519a514579ba9ec52f006c28ae19d97915951f69fa70da2c9e91"},
+ {file = "protobuf-4.23.2-cp39-cp39-win_amd64.whl", hash = "sha256:54a533b971288af3b9926e53850c7eb186886c0c84e61daa8444385a4720297f"},
+ {file = "protobuf-4.23.2-py3-none-any.whl", hash = "sha256:8da6070310d634c99c0db7df48f10da495cc283fd9e9234877f0cd182d43ab7f"},
+ {file = "protobuf-4.23.2.tar.gz", hash = "sha256:20874e7ca4436f683b64ebdbee2129a5a2c301579a67d1a7dda2cdf62fb7f5f7"},
+]
+
+[[package]]
+name = "validate-email"
+version = "1.3"
+description = "Validate_email verify if an email address is valid and really exists."
+optional = false
+python-versions = "*"
+files = [
+ {file = "validate_email-1.3.tar.gz", hash = "sha256:784719dc5f780be319cdd185dc85dd93afebdb6ebb943811bc4c7c5f9c72aeaf"},
+]
+
+[metadata]
+lock-version = "2.0"
+python-versions = "^3.10.12"
+content-hash = "306b11f0b5dbdac5310fb85892b87ed92eba95fa315d4ab70ba4d5615d98cdfb"
diff --git a/uv/spec/fixtures/poetry_locks/latest_subdep_blocked.lock b/uv/spec/fixtures/poetry_locks/latest_subdep_blocked.lock
new file mode 100644
index 00000000000..06c17248a38
--- /dev/null
+++ b/uv/spec/fixtures/poetry_locks/latest_subdep_blocked.lock
@@ -0,0 +1,65 @@
+[[package]]
+category = "main"
+description = "Python package for providing Mozilla's CA Bundle."
+name = "certifi"
+optional = false
+platform = "*"
+python-versions = "*"
+version = "2018.4.16"
+
+[[package]]
+category = "main"
+description = "Universal encoding detector for Python 2 and 3"
+name = "chardet"
+optional = false
+platform = "*"
+python-versions = "*"
+version = "3.0.4"
+
+[[package]]
+category = "main"
+description = "Internationalized Domain Names in Applications (IDNA)"
+name = "idna"
+optional = false
+platform = "UNKNOWN"
+python-versions = "*"
+version = "2.5"
+
+[[package]]
+category = "main"
+description = "Python HTTP for Humans."
+name = "requests"
+optional = false
+python-versions = "*"
+version = "2.18.4"
+
+[package.dependencies]
+certifi = ">=2017.4.17"
+chardet = ">=3.0.2,<3.1.0"
+idna = ">=2.5,<2.7"
+urllib3 = ">=1.21.1,<1.23"
+
+[package.extras]
+security = ["cryptography (>=1.3.4)", "idna (>=2.0.0)", "pyOpenSSL (>=0.14)"]
+socks = ["PySocks (>=1.5.6,<1.5.7 || >1.5.7)", "win-inet-pton"]
+
+[[package]]
+category = "main"
+description = "HTTP library with thread-safe connection pooling, file post, and more."
+name = "urllib3"
+optional = false
+platform = "*"
+python-versions = "*"
+version = "1.21.1"
+
+[metadata]
+content-hash = "a8d5762e953227a34625a209e9cc67a1c6fb2d7a971845829cf2f9cf61a5bd7c"
+platform = "*"
+python-versions = "^3.7"
+
+[metadata.hashes]
+certifi = ["13e698f54293db9f89122b0581843a782ad0934a4fe0172d2a980ba77fc61bb7", "9fa520c1bacfb634fa7af20a76bcbd3d5fb390481724c597da32c719a7dca4b0"]
+chardet = ["84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae", "fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"]
+idna = ["3cb5ce08046c4e3a560fc02f138d0ac63e00f8ce5901a56b32ec8b7994082aab", "cc19709fd6d0cbfed39ea875d29ba6d4e22c0cebc510a76d6302a28385e8bb70"]
+requests = ["6a1b267aa90cac58ac3a765d067950e7dbbf75b1da07e895d1f594193a40a38b", "9c443e7324ba5b85070c4a818ade28bfabedf16ea10206da1132edaa6dda237e"]
+urllib3 = ["8ed6d5c1ff9d6ba84677310060d6a3a78ca3072ce0684cb3c645023009c114b1", "b14486978518ca0901a76ba973d7821047409d7f726f22156b24e83fd71382a5"]
diff --git a/uv/spec/fixtures/poetry_locks/multiple_constraint_dependency.lock b/uv/spec/fixtures/poetry_locks/multiple_constraint_dependency.lock
new file mode 100644
index 00000000000..a603a84db21
--- /dev/null
+++ b/uv/spec/fixtures/poetry_locks/multiple_constraint_dependency.lock
@@ -0,0 +1,267 @@
+[[package]]
+name = "atomicwrites"
+version = "1.4.1"
+description = "Atomic file writes."
+category = "main"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+
+[[package]]
+name = "attrs"
+version = "22.1.0"
+description = "Classes Without Boilerplate"
+category = "main"
+optional = false
+python-versions = ">=3.5"
+
+[package.extras]
+dev = ["cloudpickle", "coverage[toml] (>=5.0.2)", "furo", "hypothesis", "mypy (>=0.900,!=0.940)", "pre-commit", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "sphinx", "sphinx-notfound-page", "zope.interface"]
+docs = ["furo", "sphinx", "sphinx-notfound-page", "zope.interface"]
+tests = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy (>=0.900,!=0.940)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "zope.interface"]
+tests-no-zope = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy (>=0.900,!=0.940)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins"]
+
+[[package]]
+name = "colorama"
+version = "0.4.5"
+description = "Cross-platform colored terminal text."
+category = "main"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
+
+[[package]]
+name = "importlib-metadata"
+version = "5.0.0"
+description = "Read metadata from Python packages"
+category = "main"
+optional = false
+python-versions = ">=3.7"
+
+[package.dependencies]
+typing-extensions = {version = ">=3.6.4", markers = "python_version < \"3.8\""}
+zipp = ">=0.5"
+
+[package.extras]
+docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)"]
+perf = ["ipython"]
+testing = ["flake8 (<5)", "flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)"]
+
+[[package]]
+name = "more-itertools"
+version = "8.14.0"
+description = "More routines for operating on iterables, beyond itertools"
+category = "main"
+optional = false
+python-versions = ">=3.5"
+
+[[package]]
+name = "numpy"
+version = "1.21.6"
+description = "NumPy is the fundamental package for array computing with Python."
+category = "main"
+optional = false
+python-versions = ">=3.7,<3.11"
+
+[[package]]
+name = "numpy"
+version = "1.23.3"
+description = "NumPy is the fundamental package for array computing with Python."
+category = "main"
+optional = false
+python-versions = ">=3.8"
+
+[[package]]
+name = "pluggy"
+version = "1.0.0"
+description = "plugin and hook calling mechanisms for python"
+category = "main"
+optional = false
+python-versions = ">=3.6"
+
+[package.dependencies]
+importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""}
+
+[package.extras]
+dev = ["pre-commit", "tox"]
+testing = ["pytest", "pytest-benchmark"]
+
+[[package]]
+name = "py"
+version = "1.11.0"
+description = "library with cross-python path, ini-parsing, io, code, log facilities"
+category = "main"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
+
+[[package]]
+name = "pytest"
+version = "3.7.4"
+description = "pytest: simple powerful testing with Python"
+category = "main"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+
+[package.dependencies]
+atomicwrites = ">=1.0"
+attrs = ">=17.4.0"
+colorama = {version = "*", markers = "sys_platform == \"win32\""}
+more-itertools = ">=4.0.0"
+pluggy = ">=0.7"
+py = ">=1.5.0"
+setuptools = "*"
+six = ">=1.10.0"
+
+[[package]]
+name = "setuptools"
+version = "65.4.1"
+description = "Easily download, build, install, upgrade, and uninstall Python packages"
+category = "main"
+optional = false
+python-versions = ">=3.7"
+
+[package.extras]
+docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-hoverxref (<2)", "sphinx-inline-tabs", "sphinx-notfound-page (==0.8.3)", "sphinx-reredirects", "sphinxcontrib-towncrier"]
+testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8 (<5)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "mock", "pip (>=19.1)", "pip-run (>=8.8)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"]
+testing-integration = ["build[virtualenv]", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"]
+
+[[package]]
+name = "six"
+version = "1.16.0"
+description = "Python 2 and 3 compatibility utilities"
+category = "main"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*"
+
+[[package]]
+name = "typing-extensions"
+version = "4.4.0"
+description = "Backported and Experimental Type Hints for Python 3.7+"
+category = "main"
+optional = false
+python-versions = ">=3.7"
+
+[[package]]
+name = "zipp"
+version = "3.9.0"
+description = "Backport of pathlib-compatible object wrapper for zip files"
+category = "main"
+optional = false
+python-versions = ">=3.7"
+
+[package.extras]
+docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)"]
+testing = ["flake8 (<5)", "func-timeout", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)"]
+
+[metadata]
+lock-version = "1.1"
+python-versions = "^3.7"
+content-hash = "6353cd451884d76096ea31a18f4fefa4020aa815a600c408aef1e904b47c15de"
+
+[metadata.files]
+atomicwrites = [
+ {file = "atomicwrites-1.4.1.tar.gz", hash = "sha256:81b2c9071a49367a7f770170e5eec8cb66567cfbbc8c73d20ce5ca4a8d71cf11"},
+]
+attrs = [
+ {file = "attrs-22.1.0-py2.py3-none-any.whl", hash = "sha256:86efa402f67bf2df34f51a335487cf46b1ec130d02b8d39fd248abfd30da551c"},
+ {file = "attrs-22.1.0.tar.gz", hash = "sha256:29adc2665447e5191d0e7c568fde78b21f9672d344281d0c6e1ab085429b22b6"},
+]
+colorama = [
+ {file = "colorama-0.4.5-py2.py3-none-any.whl", hash = "sha256:854bf444933e37f5824ae7bfc1e98d5bce2ebe4160d46b5edf346a89358e99da"},
+ {file = "colorama-0.4.5.tar.gz", hash = "sha256:e6c6b4334fc50988a639d9b98aa429a0b57da6e17b9a44f0451f930b6967b7a4"},
+]
+importlib-metadata = [
+ {file = "importlib_metadata-5.0.0-py3-none-any.whl", hash = "sha256:ddb0e35065e8938f867ed4928d0ae5bf2a53b7773871bfe6bcc7e4fcdc7dea43"},
+ {file = "importlib_metadata-5.0.0.tar.gz", hash = "sha256:da31db32b304314d044d3c12c79bd59e307889b287ad12ff387b3500835fc2ab"},
+]
+more-itertools = [
+ {file = "more-itertools-8.14.0.tar.gz", hash = "sha256:c09443cd3d5438b8dafccd867a6bc1cb0894389e90cb53d227456b0b0bccb750"},
+ {file = "more_itertools-8.14.0-py3-none-any.whl", hash = "sha256:1bc4f91ee5b1b31ac7ceacc17c09befe6a40a503907baf9c839c229b5095cfd2"},
+]
+numpy = [
+ {file = "numpy-1.21.6-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:8737609c3bbdd48e380d463134a35ffad3b22dc56295eff6f79fd85bd0eeeb25"},
+ {file = "numpy-1.21.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:fdffbfb6832cd0b300995a2b08b8f6fa9f6e856d562800fea9182316d99c4e8e"},
+ {file = "numpy-1.21.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3820724272f9913b597ccd13a467cc492a0da6b05df26ea09e78b171a0bb9da6"},
+ {file = "numpy-1.21.6-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f17e562de9edf691a42ddb1eb4a5541c20dd3f9e65b09ded2beb0799c0cf29bb"},
+ {file = "numpy-1.21.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5f30427731561ce75d7048ac254dbe47a2ba576229250fb60f0fb74db96501a1"},
+ {file = "numpy-1.21.6-cp310-cp310-win32.whl", hash = "sha256:d4bf4d43077db55589ffc9009c0ba0a94fa4908b9586d6ccce2e0b164c86303c"},
+ {file = "numpy-1.21.6-cp310-cp310-win_amd64.whl", hash = "sha256:d136337ae3cc69aa5e447e78d8e1514be8c3ec9b54264e680cf0b4bd9011574f"},
+ {file = "numpy-1.21.6-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:6aaf96c7f8cebc220cdfc03f1d5a31952f027dda050e5a703a0d1c396075e3e7"},
+ {file = "numpy-1.21.6-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:67c261d6c0a9981820c3a149d255a76918278a6b03b6a036800359aba1256d46"},
+ {file = "numpy-1.21.6-cp37-cp37m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:a6be4cb0ef3b8c9250c19cc122267263093eee7edd4e3fa75395dfda8c17a8e2"},
+ {file = "numpy-1.21.6-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7c4068a8c44014b2d55f3c3f574c376b2494ca9cc73d2f1bd692382b6dffe3db"},
+ {file = "numpy-1.21.6-cp37-cp37m-win32.whl", hash = "sha256:7c7e5fa88d9ff656e067876e4736379cc962d185d5cd808014a8a928d529ef4e"},
+ {file = "numpy-1.21.6-cp37-cp37m-win_amd64.whl", hash = "sha256:bcb238c9c96c00d3085b264e5c1a1207672577b93fa666c3b14a45240b14123a"},
+ {file = "numpy-1.21.6-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:82691fda7c3f77c90e62da69ae60b5ac08e87e775b09813559f8901a88266552"},
+ {file = "numpy-1.21.6-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:643843bcc1c50526b3a71cd2ee561cf0d8773f062c8cbaf9ffac9fdf573f83ab"},
+ {file = "numpy-1.21.6-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:357768c2e4451ac241465157a3e929b265dfac85d9214074985b1786244f2ef3"},
+ {file = "numpy-1.21.6-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:9f411b2c3f3d76bba0865b35a425157c5dcf54937f82bbeb3d3c180789dd66a6"},
+ {file = "numpy-1.21.6-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:4aa48afdce4660b0076a00d80afa54e8a97cd49f457d68a4342d188a09451c1a"},
+ {file = "numpy-1.21.6-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d6a96eef20f639e6a97d23e57dd0c1b1069a7b4fd7027482a4c5c451cd7732f4"},
+ {file = "numpy-1.21.6-cp38-cp38-win32.whl", hash = "sha256:5c3c8def4230e1b959671eb959083661b4a0d2e9af93ee339c7dada6759a9470"},
+ {file = "numpy-1.21.6-cp38-cp38-win_amd64.whl", hash = "sha256:bf2ec4b75d0e9356edea834d1de42b31fe11f726a81dfb2c2112bc1eaa508fcf"},
+ {file = "numpy-1.21.6-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:4391bd07606be175aafd267ef9bea87cf1b8210c787666ce82073b05f202add1"},
+ {file = "numpy-1.21.6-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:67f21981ba2f9d7ba9ade60c9e8cbaa8cf8e9ae51673934480e45cf55e953673"},
+ {file = "numpy-1.21.6-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ee5ec40fdd06d62fe5d4084bef4fd50fd4bb6bfd2bf519365f569dc470163ab0"},
+ {file = "numpy-1.21.6-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:1dbe1c91269f880e364526649a52eff93ac30035507ae980d2fed33aaee633ac"},
+ {file = "numpy-1.21.6-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:d9caa9d5e682102453d96a0ee10c7241b72859b01a941a397fd965f23b3e016b"},
+ {file = "numpy-1.21.6-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:58459d3bad03343ac4b1b42ed14d571b8743dc80ccbf27444f266729df1d6f5b"},
+ {file = "numpy-1.21.6-cp39-cp39-win32.whl", hash = "sha256:7f5ae4f304257569ef3b948810816bc87c9146e8c446053539947eedeaa32786"},
+ {file = "numpy-1.21.6-cp39-cp39-win_amd64.whl", hash = "sha256:e31f0bb5928b793169b87e3d1e070f2342b22d5245c755e2b81caa29756246c3"},
+ {file = "numpy-1.21.6-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:dd1c8f6bd65d07d3810b90d02eba7997e32abbdf1277a481d698969e921a3be0"},
+ {file = "numpy-1.21.6.zip", hash = "sha256:ecb55251139706669fdec2ff073c98ef8e9a84473e51e716211b41aa0f18e656"},
+ {file = "numpy-1.23.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c9f707b5bb73bf277d812ded9896f9512a43edff72712f31667d0a8c2f8e71ee"},
+ {file = "numpy-1.23.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ffcf105ecdd9396e05a8e58e81faaaf34d3f9875f137c7372450baa5d77c9a54"},
+ {file = "numpy-1.23.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ea3f98a0ffce3f8f57675eb9119f3f4edb81888b6874bc1953f91e0b1d4f440"},
+ {file = "numpy-1.23.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:004f0efcb2fe1c0bd6ae1fcfc69cc8b6bf2407e0f18be308612007a0762b4089"},
+ {file = "numpy-1.23.3-cp310-cp310-win32.whl", hash = "sha256:98dcbc02e39b1658dc4b4508442a560fe3ca5ca0d989f0df062534e5ca3a5c1a"},
+ {file = "numpy-1.23.3-cp310-cp310-win_amd64.whl", hash = "sha256:39a664e3d26ea854211867d20ebcc8023257c1800ae89773cbba9f9e97bae036"},
+ {file = "numpy-1.23.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1f27b5322ac4067e67c8f9378b41c746d8feac8bdd0e0ffede5324667b8a075c"},
+ {file = "numpy-1.23.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2ad3ec9a748a8943e6eb4358201f7e1c12ede35f510b1a2221b70af4bb64295c"},
+ {file = "numpy-1.23.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bdc9febce3e68b697d931941b263c59e0c74e8f18861f4064c1f712562903411"},
+ {file = "numpy-1.23.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:301c00cf5e60e08e04d842fc47df641d4a181e651c7135c50dc2762ffe293dbd"},
+ {file = "numpy-1.23.3-cp311-cp311-win32.whl", hash = "sha256:7cd1328e5bdf0dee621912f5833648e2daca72e3839ec1d6695e91089625f0b4"},
+ {file = "numpy-1.23.3-cp311-cp311-win_amd64.whl", hash = "sha256:8355fc10fd33a5a70981a5b8a0de51d10af3688d7a9e4a34fcc8fa0d7467bb7f"},
+ {file = "numpy-1.23.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:bc6e8da415f359b578b00bcfb1d08411c96e9a97f9e6c7adada554a0812a6cc6"},
+ {file = "numpy-1.23.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:22d43376ee0acd547f3149b9ec12eec2f0ca4a6ab2f61753c5b29bb3e795ac4d"},
+ {file = "numpy-1.23.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a64403f634e5ffdcd85e0b12c08f04b3080d3e840aef118721021f9b48fc1460"},
+ {file = "numpy-1.23.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:efd9d3abe5774404becdb0748178b48a218f1d8c44e0375475732211ea47c67e"},
+ {file = "numpy-1.23.3-cp38-cp38-win32.whl", hash = "sha256:f8c02ec3c4c4fcb718fdf89a6c6f709b14949408e8cf2a2be5bfa9c49548fd85"},
+ {file = "numpy-1.23.3-cp38-cp38-win_amd64.whl", hash = "sha256:e868b0389c5ccfc092031a861d4e158ea164d8b7fdbb10e3b5689b4fc6498df6"},
+ {file = "numpy-1.23.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:09f6b7bdffe57fc61d869a22f506049825d707b288039d30f26a0d0d8ea05164"},
+ {file = "numpy-1.23.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8c79d7cf86d049d0c5089231a5bcd31edb03555bd93d81a16870aa98c6cfb79d"},
+ {file = "numpy-1.23.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e5d5420053bbb3dd64c30e58f9363d7a9c27444c3648e61460c1237f9ec3fa14"},
+ {file = "numpy-1.23.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d5422d6a1ea9b15577a9432e26608c73a78faf0b9039437b075cf322c92e98e7"},
+ {file = "numpy-1.23.3-cp39-cp39-win32.whl", hash = "sha256:c1ba66c48b19cc9c2975c0d354f24058888cdc674bebadceb3cdc9ec403fb5d1"},
+ {file = "numpy-1.23.3-cp39-cp39-win_amd64.whl", hash = "sha256:78a63d2df1d947bd9d1b11d35564c2f9e4b57898aae4626638056ec1a231c40c"},
+ {file = "numpy-1.23.3-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:17c0e467ade9bda685d5ac7f5fa729d8d3e76b23195471adae2d6a6941bd2c18"},
+ {file = "numpy-1.23.3-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:91b8d6768a75247026e951dce3b2aac79dc7e78622fc148329135ba189813584"},
+ {file = "numpy-1.23.3-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:94c15ca4e52671a59219146ff584488907b1f9b3fc232622b47e2cf832e94fb8"},
+ {file = "numpy-1.23.3.tar.gz", hash = "sha256:51bf49c0cd1d52be0a240aa66f3458afc4b95d8993d2d04f0d91fa60c10af6cd"},
+]
+pluggy = [
+ {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"},
+ {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"},
+]
+py = [
+ {file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"},
+ {file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"},
+]
+pytest = [
+ {file = "pytest-3.7.4-py2.py3-none-any.whl", hash = "sha256:ad0c7db7b5d4081631e0155f5c61b80ad76ce148551aaafe3a718d65a7508b18"},
+ {file = "pytest-3.7.4.tar.gz", hash = "sha256:2d7c49e931316cc7d1638a3e5f54f5d7b4e5225972b3c9838f3584788d27f349"},
+]
+setuptools = [
+ {file = "setuptools-65.4.1-py3-none-any.whl", hash = "sha256:1b6bdc6161661409c5f21508763dc63ab20a9ac2f8ba20029aaaa7fdb9118012"},
+ {file = "setuptools-65.4.1.tar.gz", hash = "sha256:3050e338e5871e70c72983072fe34f6032ae1cdeeeb67338199c2f74e083a80e"},
+]
+six = [
+ {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"},
+ {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"},
+]
+typing-extensions = [
+ {file = "typing_extensions-4.4.0-py3-none-any.whl", hash = "sha256:16fa4864408f655d35ec496218b85f79b3437c829e93320c7c9215ccfd92489e"},
+ {file = "typing_extensions-4.4.0.tar.gz", hash = "sha256:1511434bb92bf8dd198c12b1cc812e800d4181cfcb867674e0f8279cc93087aa"},
+]
+zipp = [
+ {file = "zipp-3.9.0-py3-none-any.whl", hash = "sha256:972cfa31bc2fedd3fa838a51e9bc7e64b7fb725a8c00e7431554311f180e9980"},
+ {file = "zipp-3.9.0.tar.gz", hash = "sha256:3a7af91c3db40ec72dd9d154ae18e008c69efe8ca88dde4f9a731bb82fe2f9eb"},
+]
diff --git a/uv/spec/fixtures/poetry_locks/pdm_example.lock b/uv/spec/fixtures/poetry_locks/pdm_example.lock
new file mode 100644
index 00000000000..c4faae860d9
--- /dev/null
+++ b/uv/spec/fixtures/poetry_locks/pdm_example.lock
@@ -0,0 +1,140 @@
+[[package]]
+name = "certifi"
+version = "2022.9.24"
+requires_python = ">=3.6"
+summary = "Python package for providing Mozilla's CA Bundle."
+
+[[package]]
+name = "charset-normalizer"
+version = "2.0.12"
+requires_python = ">=3.5.0"
+summary = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet."
+
+[[package]]
+name = "flake8"
+version = "3.9.2"
+requires_python = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7"
+summary = "the modular source code checker: pep8 pyflakes and co"
+dependencies = [
+ "importlib-metadata; python_version < \"3.8\"",
+ "mccabe<0.7.0,>=0.6.0",
+ "pycodestyle<2.8.0,>=2.7.0",
+ "pyflakes<2.4.0,>=2.3.0",
+]
+
+[[package]]
+name = "idna"
+version = "3.4"
+requires_python = ">=3.5"
+summary = "Internationalized Domain Names in Applications (IDNA)"
+
+[[package]]
+name = "importlib-metadata"
+version = "4.8.3"
+requires_python = ">=3.6"
+summary = "Read metadata from Python packages"
+dependencies = [
+ "typing-extensions>=3.6.4; python_version < \"3.8\"",
+ "zipp>=0.5",
+]
+
+[[package]]
+name = "mccabe"
+version = "0.6.1"
+summary = "McCabe checker, plugin for flake8"
+
+[[package]]
+name = "pycodestyle"
+version = "2.7.0"
+requires_python = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+summary = "Python style guide checker"
+
+[[package]]
+name = "pyflakes"
+version = "2.3.1"
+requires_python = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+summary = "passive checker of Python programs"
+
+[[package]]
+name = "requests"
+version = "2.27.1"
+requires_python = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*"
+summary = "Python HTTP for Humans."
+dependencies = [
+ "certifi>=2017.4.17",
+ "charset-normalizer~=2.0.0; python_version >= \"3\"",
+ "idna<4,>=2.5; python_version >= \"3\"",
+ "urllib3<1.27,>=1.21.1",
+]
+
+[[package]]
+name = "typing-extensions"
+version = "4.1.1"
+requires_python = ">=3.6"
+summary = "Backported and Experimental Type Hints for Python 3.6+"
+
+[[package]]
+name = "urllib3"
+version = "1.26.12"
+requires_python = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, <4"
+summary = "HTTP library with thread-safe connection pooling, file post, and more."
+
+[[package]]
+name = "zipp"
+version = "3.6.0"
+requires_python = ">=3.6"
+summary = "Backport of pathlib-compatible object wrapper for zip files"
+
+[metadata]
+lock_version = "4.0"
+content_hash = "sha256:14105ab2be152f8aab79a29878099026d06375acc7b647029d24ef620399442b"
+
+[metadata.files]
+"certifi 2022.9.24" = [
+ {url = "https://files.pythonhosted.org/packages/1d/38/fa96a426e0c0e68aabc68e896584b83ad1eec779265a028e156ce509630e/certifi-2022.9.24-py3-none-any.whl", hash = "sha256:90c1a32f1d68f940488354e36370f6cca89f0f106db09518524c88d6ed83f382"},
+ {url = "https://files.pythonhosted.org/packages/cb/a4/7de7cd59e429bd0ee6521ba58a75adaec136d32f91a761b28a11d8088d44/certifi-2022.9.24.tar.gz", hash = "sha256:0d9c601124e5a6ba9712dbc60d9c53c21e34f5f641fe83002317394311bdce14"},
+]
+"charset-normalizer 2.0.12" = [
+ {url = "https://files.pythonhosted.org/packages/06/b3/24afc8868eba069a7f03650ac750a778862dc34941a4bebeb58706715726/charset_normalizer-2.0.12-py3-none-any.whl", hash = "sha256:6881edbebdb17b39b4eaaa821b438bf6eddffb4468cf344f09f89def34a8b1df"},
+ {url = "https://files.pythonhosted.org/packages/56/31/7bcaf657fafb3c6db8c787a865434290b726653c912085fbd371e9b92e1c/charset-normalizer-2.0.12.tar.gz", hash = "sha256:2857e29ff0d34db842cd7ca3230549d1a697f96ee6d3fb071cfa6c7393832597"},
+]
+"flake8 3.9.2" = [
+ {url = "https://files.pythonhosted.org/packages/9e/47/15b267dfe7e03dca4c4c06e7eadbd55ef4dfd368b13a0bab36d708b14366/flake8-3.9.2.tar.gz", hash = "sha256:07528381786f2a6237b061f6e96610a4167b226cb926e2aa2b6b1d78057c576b"},
+ {url = "https://files.pythonhosted.org/packages/fc/80/35a0716e5d5101e643404dabd20f07f5528a21f3ef4032d31a49c913237b/flake8-3.9.2-py2.py3-none-any.whl", hash = "sha256:bf8fd333346d844f616e8d47905ef3a3384edae6b4e9beb0c5101e25e3110907"},
+]
+"idna 3.4" = [
+ {url = "https://files.pythonhosted.org/packages/8b/e1/43beb3d38dba6cb420cefa297822eac205a277ab43e5ba5d5c46faf96438/idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"},
+ {url = "https://files.pythonhosted.org/packages/fc/34/3030de6f1370931b9dbb4dad48f6ab1015ab1d32447850b9fc94e60097be/idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"},
+]
+"importlib-metadata 4.8.3" = [
+ {url = "https://files.pythonhosted.org/packages/85/ed/e65128cc5cb1580f22ee3009d9187ecdfcc43ffb3b581fe854b24e87d8e7/importlib_metadata-4.8.3.tar.gz", hash = "sha256:766abffff765960fcc18003801f7044eb6755ffae4521c8e8ce8e83b9c9b0668"},
+ {url = "https://files.pythonhosted.org/packages/a0/a1/b153a0a4caf7a7e3f15c2cd56c7702e2cf3d89b1b359d1f1c5e59d68f4ce/importlib_metadata-4.8.3-py3-none-any.whl", hash = "sha256:65a9576a5b2d58ca44d133c42a241905cc45e34d2c06fd5ba2bafa221e5d7b5e"},
+]
+"mccabe 0.6.1" = [
+ {url = "https://files.pythonhosted.org/packages/06/18/fa675aa501e11d6d6ca0ae73a101b2f3571a565e0f7d38e062eec18a91ee/mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"},
+ {url = "https://files.pythonhosted.org/packages/87/89/479dc97e18549e21354893e4ee4ef36db1d237534982482c3681ee6e7b57/mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42"},
+]
+"pycodestyle 2.7.0" = [
+ {url = "https://files.pythonhosted.org/packages/02/b3/c832123f2699892c715fcdfebb1a8fdeffa11bb7b2350e46ecdd76b45a20/pycodestyle-2.7.0.tar.gz", hash = "sha256:c389c1d06bf7904078ca03399a4816f974a1d590090fecea0c63ec26ebaf1cef"},
+ {url = "https://files.pythonhosted.org/packages/de/cc/227251b1471f129bc35e966bb0fceb005969023926d744139642d847b7ae/pycodestyle-2.7.0-py2.py3-none-any.whl", hash = "sha256:514f76d918fcc0b55c6680472f0a37970994e07bbb80725808c17089be302068"},
+]
+"pyflakes 2.3.1" = [
+ {url = "https://files.pythonhosted.org/packages/6c/11/2a745612f1d3cbbd9c69ba14b1b43a35a2f5c3c81cd0124508c52c64307f/pyflakes-2.3.1-py2.py3-none-any.whl", hash = "sha256:7893783d01b8a89811dd72d7dfd4d84ff098e5eed95cfa8905b22bbffe52efc3"},
+ {url = "https://files.pythonhosted.org/packages/a8/0f/0dc480da9162749bf629dca76570972dd9cce5bedc60196a3c912875c87d/pyflakes-2.3.1.tar.gz", hash = "sha256:f5bc8ecabc05bb9d291eb5203d6810b49040f6ff446a756326104746cc00c1db"},
+]
+"requests 2.27.1" = [
+ {url = "https://files.pythonhosted.org/packages/2d/61/08076519c80041bc0ffa1a8af0cbd3bf3e2b62af10435d269a9d0f40564d/requests-2.27.1-py2.py3-none-any.whl", hash = "sha256:f22fa1e554c9ddfd16e6e41ac79759e17be9e492b3587efa038054674760e72d"},
+ {url = "https://files.pythonhosted.org/packages/60/f3/26ff3767f099b73e0efa138a9998da67890793bfa475d8278f84a30fec77/requests-2.27.1.tar.gz", hash = "sha256:68d7c56fd5a8999887728ef304a6d12edc7be74f1cfa47714fc8b414525c9a61"},
+]
+"typing-extensions 4.1.1" = [
+ {url = "https://files.pythonhosted.org/packages/45/6b/44f7f8f1e110027cf88956b59f2fad776cca7e1704396d043f89effd3a0e/typing_extensions-4.1.1-py3-none-any.whl", hash = "sha256:21c85e0fe4b9a155d0799430b0ad741cdce7e359660ccbd8b530613e8df88ce2"},
+ {url = "https://files.pythonhosted.org/packages/b1/5a/8b5fbb891ef3f81fc923bf3cb4a578c0abf9471eb50ce0f51c74212182ab/typing_extensions-4.1.1.tar.gz", hash = "sha256:1a9462dcc3347a79b1f1c0271fbe79e844580bb598bafa1ed208b94da3cdcd42"},
+]
+"urllib3 1.26.12" = [
+ {url = "https://files.pythonhosted.org/packages/6f/de/5be2e3eed8426f871b170663333a0f627fc2924cc386cd41be065e7ea870/urllib3-1.26.12-py2.py3-none-any.whl", hash = "sha256:b930dd878d5a8afb066a637fbb35144fe7901e3b209d1cd4f524bd0e9deee997"},
+ {url = "https://files.pythonhosted.org/packages/b2/56/d87d6d3c4121c0bcec116919350ca05dc3afd2eeb7dc88d07e8083f8ea94/urllib3-1.26.12.tar.gz", hash = "sha256:3fa96cf423e6987997fc326ae8df396db2a8b7c667747d47ddd8ecba91f4a74e"},
+]
+"zipp 3.6.0" = [
+ {url = "https://files.pythonhosted.org/packages/02/bf/0d03dbdedb83afec081fefe86cae3a2447250ef1a81ac601a9a56e785401/zipp-3.6.0.tar.gz", hash = "sha256:71c644c5369f4a6e07636f0aa966270449561fcea2e3d6747b8d23efaa9d7832"},
+ {url = "https://files.pythonhosted.org/packages/bd/df/d4a4974a3e3957fd1c1fa3082366d7fff6e428ddb55f074bf64876f8e8ad/zipp-3.6.0-py3-none-any.whl", hash = "sha256:9fe5ea21568a0a70e50f273397638d39b03353731e6cbbb3fd8502a33fec40bc"},
+]
diff --git a/uv/spec/fixtures/poetry_locks/poetry.lock b/uv/spec/fixtures/poetry_locks/poetry.lock
new file mode 100644
index 00000000000..70a551c32a0
--- /dev/null
+++ b/uv/spec/fixtures/poetry_locks/poetry.lock
@@ -0,0 +1,424 @@
+[[package]]
+name = "appdirs"
+version = "1.4.3"
+description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
+category = "dev"
+optional = false
+python-versions = "*"
+platform = "*"
+
+[[package]]
+name = "atomicwrites"
+version = "1.1.5"
+description = "Atomic file writes."
+category = "dev"
+optional = false
+python-versions = "*"
+platform = "UNKNOWN"
+
+[[package]]
+name = "attrs"
+version = "18.1.0"
+description = "Classes Without Boilerplate"
+category = "dev"
+optional = false
+python-versions = "*"
+platform = "*"
+
+[[package]]
+name = "black"
+version = "18.6b1"
+description = "The uncompromising code formatter."
+category = "dev"
+optional = false
+python-versions = ">=3.6"
+platform = "*"
+
+[package.dependencies]
+click = ">=6.5"
+attrs = ">=17.4.0"
+appdirs = "*"
+[[package]]
+name = "certifi"
+version = "2018.4.16"
+description = "Python package for providing Mozilla's CA Bundle."
+category = "main"
+optional = false
+python-versions = "*"
+platform = "*"
+
+[[package]]
+name = "chardet"
+version = "3.0.4"
+description = "Universal encoding detector for Python 2 and 3"
+category = "main"
+optional = false
+python-versions = "*"
+platform = "*"
+
+[[package]]
+name = "click"
+version = "6.7"
+description = "A simple wrapper around optparse for powerful command line utilities."
+category = "dev"
+optional = false
+python-versions = "*"
+platform = "*"
+
+[[package]]
+name = "colorama"
+version = "0.3.9"
+description = "Cross-platform colored terminal text."
+category = "dev"
+optional = false
+python-versions = "*"
+platform = "UNKNOWN"
+
+[package.requirements]
+platform = "win32"
+[[package]]
+name = "coverage"
+version = "4.5.1"
+description = "Code coverage measurement for Python"
+category = "dev"
+optional = false
+python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*, <4"
+platform = "*"
+
+[[package]]
+name = "flake8"
+version = "3.5.0"
+description = "the modular source code checker: pep8, pyflakes and co"
+category = "dev"
+optional = false
+python-versions = "*"
+platform = "*"
+
+[package.dependencies]
+enum34 = "*"
+configparser = "*"
+pyflakes = ">=1.5.0,<1.7.0"
+pycodestyle = ">=2.0.0,<2.4.0"
+mccabe = ">=0.6.0,<0.7.0"
+[[package]]
+name = "flake8-comprehensions"
+version = "1.4.1"
+description = "A flake8 plugin to help you write better list/set/dict comprehensions."
+category = "dev"
+optional = false
+python-versions = "*"
+platform = "*"
+
+[package.dependencies]
+flake8 = "<3.2.0 || >3.2.0"
+[[package]]
+name = "geographiclib"
+version = "1.49"
+description = "The geodesic routines from GeographicLib"
+category = "main"
+optional = false
+python-versions = "*"
+platform = "*"
+
+[[package]]
+name = "geopy"
+version = "1.14.0"
+description = "Python Geocoding Toolbox"
+category = "main"
+optional = false
+python-versions = "*"
+platform = "*"
+
+[package.dependencies]
+geographiclib = ">=1.49,<2"
+[[package]]
+name = "httmock"
+version = "1.2.6"
+description = "A mocking library for requests."
+category = "dev"
+optional = false
+python-versions = "*"
+platform = "UNKNOWN"
+
+[package.dependencies]
+requests = ">=1.0.0"
+[[package]]
+name = "hypothesis"
+version = "3.57.0"
+description = "A library for property based testing"
+category = "dev"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+platform = "*"
+
+[package.dependencies]
+attrs = ">=16.0.0"
+coverage = "*"
+enum34 = "*"
+[[package]]
+name = "idna"
+version = "2.6"
+description = "Internationalized Domain Names in Applications (IDNA)"
+category = "main"
+optional = false
+python-versions = "*"
+platform = "*"
+
+[[package]]
+name = "mccabe"
+version = "0.6.1"
+description = "McCabe checker, plugin for flake8"
+category = "dev"
+optional = false
+python-versions = "*"
+platform = "*"
+
+[[package]]
+name = "more-itertools"
+version = "4.2.0"
+description = "More routines for operating on iterables, beyond itertools"
+category = "dev"
+optional = false
+python-versions = "*"
+platform = "*"
+
+[package.dependencies]
+six = ">=1.0.0,<2.0.0"
+[[package]]
+name = "mypy"
+version = "0.600"
+description = "Optional static typing for Python"
+category = "dev"
+optional = false
+python-versions = "*"
+platform = "*"
+
+[package.dependencies]
+typing = ">=3.5.3"
+typed-ast = ">=1.1.0,<1.2.0"
+[[package]]
+name = "pillow"
+version = "5.1.0"
+description = "Python Imaging Library (Fork)"
+category = "main"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+platform = "*"
+
+[[package]]
+name = "pluggy"
+version = "0.6.0"
+description = "plugin and hook calling mechanisms for python"
+category = "dev"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+platform = "unix"
+
+[[package]]
+name = "py"
+version = "1.5.3"
+description = "library with cross-python path, ini-parsing, io, code, log facilities"
+category = "dev"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+platform = "unix"
+
+[[package]]
+name = "pycodestyle"
+version = "2.3.1"
+description = "Python style guide checker"
+category = "dev"
+optional = false
+python-versions = "*"
+platform = "*"
+
+[[package]]
+name = "pyflakes"
+version = "1.6.0"
+description = "passive checker of Python programs"
+category = "dev"
+optional = false
+python-versions = "*"
+platform = "*"
+
+[[package]]
+name = "pytest"
+version = "3.6.1"
+description = "pytest: simple powerful testing with Python"
+category = "dev"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+platform = "unix"
+
+[package.dependencies]
+colorama = "*"
+funcsigs = "*"
+pluggy = ">=0.5,<0.7"
+atomicwrites = ">=1.0"
+more-itertools = ">=4.0.0"
+attrs = ">=17.4.0"
+setuptools = "*"
+six = ">=1.10.0"
+py = ">=1.5.0"
+[[package]]
+name = "pytest-cov"
+version = "2.5.1"
+description = "Pytest plugin for measuring coverage."
+category = "dev"
+optional = false
+python-versions = "*"
+platform = "*"
+
+[package.dependencies]
+coverage = ">=3.7.1"
+pytest = ">=2.6.0"
+[[package]]
+name = "pytest-mock"
+version = "1.10.0"
+description = "Thin-wrapper around the mock package for easier use with py.test"
+category = "dev"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+platform = "any"
+
+[package.dependencies]
+mock = "*"
+pytest = ">=2.7"
+[[package]]
+name = "pytest-random-order"
+version = "0.7.0"
+description = "Randomise the order in which pytest tests are run with some control over the randomness"
+category = "dev"
+optional = false
+python-versions = "*"
+platform = "*"
+
+[package.dependencies]
+pytest = ">=2.9.2"
+[[package]]
+name = "pytest-sugar"
+version = "0.9.1"
+description = "py.test is a plugin for py.test that changes the default look and feel of py.test (e.g. progressbar, show tests that fail instantly)."
+category = "dev"
+optional = false
+python-versions = "*"
+platform = "any"
+
+[package.dependencies]
+pytest = ">=2.9"
+termcolor = ">=1.1.0"
+[[package]]
+name = "requests"
+version = "2.18.4"
+description = "Python HTTP for Humans."
+category = "main"
+optional = false
+python-versions = "*"
+platform = "*"
+
+[package.dependencies]
+certifi = ">=2017.4.17"
+chardet = ">=3.0.2,<3.1.0"
+idna = ">=2.5,<2.7"
+urllib3 = ">=1.21.1,<1.23"
+[[package]]
+name = "six"
+version = "1.11.0"
+description = "Python 2 and 3 compatibility utilities"
+category = "dev"
+optional = false
+python-versions = "*"
+platform = "*"
+
+[[package]]
+name = "termcolor"
+version = "1.1.0"
+description = "ANSII Color formatting for output in terminal."
+category = "dev"
+optional = false
+python-versions = "*"
+platform = "UNKNOWN"
+
+[[package]]
+name = "tox"
+version = "3.0.0"
+description = "virtualenv-based automation of test activities"
+category = "dev"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+platform = "unix"
+
+[package.dependencies]
+virtualenv = ">=1.11.2"
+six = "*"
+pluggy = ">=0.3.0,<1.0"
+py = ">=1.4.17"
+[[package]]
+name = "typed-ast"
+version = "1.1.0"
+description = "a fork of Python 2 and 3 ast modules with type comment support"
+category = "dev"
+optional = false
+python-versions = "*"
+platform = "POSIX"
+
+[[package]]
+name = "urllib3"
+version = "1.22"
+description = "HTTP library with thread-safe connection pooling, file post, and more."
+category = "main"
+optional = false
+python-versions = "*"
+platform = "*"
+
+[[package]]
+name = "virtualenv"
+version = "16.0.0"
+description = "Virtual Python Environment builder"
+category = "dev"
+optional = false
+python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*"
+platform = "*"
+
+[metadata]
+python-versions = "^3.7"
+platform = "*"
+content-hash = "ee304fb3aa8d4516585e9fa28f655f28afecea1cdaf9474b2b4fb25510aad40d"
+
+[metadata.hashes]
+appdirs = [ "d8b24664561d0d34ddfaec54636d502d7cea6e29c3eaf68f3df6180863e2166e", "9e5896d1372858f8dd3344faf4e5014d21849c756c8d5701f78f8a103b372d92",]
+atomicwrites = [ "a24da68318b08ac9c9c45029f4a10371ab5b20e4226738e150e6e7c571630ae6", "240831ea22da9ab882b551b31d4225591e5e447a68c5e188db5b89ca1d487585",]
+attrs = [ "4b90b09eeeb9b88c35bc642cbac057e45a5fd85367b985bd2809c62b7b939265", "e0d0eb91441a3b53dab4d9b743eafc1ac44476296a2053b6ca3af0b139faf87b",]
+black = [ "80dbe2103e937de543942b7946fe71adc387506fe1922018e2b97555513a35fc", "0c07b68fc6fc4df8b09873e81893d7b77d52794fa3431d8843b590bc33956105",]
+certifi = [ "9fa520c1bacfb634fa7af20a76bcbd3d5fb390481724c597da32c719a7dca4b0", "13e698f54293db9f89122b0581843a782ad0934a4fe0172d2a980ba77fc61bb7",]
+chardet = [ "fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691", "84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae",]
+click = [ "29f99fc6125fbc931b758dc053b3114e55c77a6e4c6c3a2674a2dc986016381d", "f15516df478d5a56180fbf80e68f206010e6d160fc39fa508b65e035fd75130b",]
+colorama = [ "463f8483208e921368c9f306094eb6f725c6ca42b0f97e313cb5d5512459feda", "48eb22f4f8461b1df5734a074b57042430fb06e1d61bd1e11b078c0fe6d7a1f1",]
+coverage = [ "7608a3dd5d73cb06c531b8925e0ef8d3de31fed2544a7de6c63960a1e73ea4bc", "3a2184c6d797a125dca8367878d3b9a178b6fdd05fdc2d35d758c3006a1cd694", "f3f501f345f24383c0000395b26b726e46758b71393267aeae0bd36f8b3ade80", "0b136648de27201056c1869a6c0d4e23f464750fd9a9ba9750b8336a244429ed", "337ded681dd2ef9ca04ef5d93cfc87e52e09db2594c296b4a0a3662cb1b41249", "3eb42bf89a6be7deb64116dd1cc4b08171734d721e7a7e57ad64cc4ef29ed2f1", "be6cfcd8053d13f5f5eeb284aa8a814220c3da1b0078fa859011c7fffd86dab9", "69bf008a06b76619d3c3f3b1983f5145c75a305a0fea513aca094cae5c40a8f5", "2eb564bbf7816a9d68dd3369a510be3327f1c618d2357fa6b1216994c2e3d508", "9d6dd10d49e01571bf6e147d3b505141ffc093a06756c60b053a859cb2128b1f", "701cd6093d63e6b8ad7009d8a92425428bc4d6e7ab8d75efbb665c806c1d79ba", "5a13ea7911ff5e1796b6d5e4fbbf6952381a611209b736d48e675c2756f3f74e", "c1bb572fab8208c400adaf06a8133ac0712179a334c09224fb11393e920abcdd", "03481e81d558d30d230bc12999e3edffe392d244349a90f4ef9b88425fac74ba", "28b2191e7283f4f3568962e373b47ef7f0392993bb6660d079c62bd50fe9d162", "de4418dadaa1c01d497e539210cb6baa015965526ff5afc078c57ca69160108d", "8c3cb8c35ec4d9506979b4cf90ee9918bc2e49f84189d9bf5c36c0c1119c6558", "7e1fe19bd6dce69d9fd159d8e4a80a8f52101380d5d3a4d374b6d3eae0e5de9c", "6bc583dc18d5979dc0f6cec26a8603129de0304d5ae1f17e57a12834e7235062", "198626739a79b09fa0a2f06e083ffd12eb55449b5f8bfdbeed1df4910b2ca640", "7aa36d2b844a3e4a4b356708d79fd2c260281a7390d678a10b91ca595ddc9e99", "3d72c20bd105022d29b14a7d628462ebdc61de2f303322c0212a054352f3b287", "4635a184d0bbe537aa185a34193898eee409332a8ccb27eea36f262566585000", "e05cb4d9aad6233d67e0541caa7e511fa4047ed7750ec2510d466e806e0255d6", "76ecd006d1d8f739430ec50cc872889af1f9c1b6b8f48e29941814b09b0fd3cc", "7d3f553904b0c5c016d1dad058a7554c7ac4c91a789fca496e7d8347ad040653", "3c79a6f7b95751cdebcd9037e4d06f8d5a9b60e4ed0cd231342aa8ad7124882a", "56e448f051a201c5ebbaa86a5efd0ca90d327204d8b059ab25ad0f35fbfd79f1", "ac4fef68da01116a5c117eba4dd46f2e06847a497de5ed1d64bb99a5fda1ef91", "1c383d2ef13ade2acc636556fd544dba6e14fa30755f26812f54300e401f98f2", "b8815995e050764c8610dbc82641807d196927c3dbed207f0a079833ffcf588d", "104ab3934abaf5be871a583541e8829d6c19ce7bde2923b2751e0d3ca44db60a", "9e112fcbe0148a6fa4f0a02e8d58e94470fc6cb82a5481618fea901699bf34c4", "15b111b6a0f46ee1a485414a52a7ad1d703bdf984e9ed3c288a4414d3871dcbd", "e4d96c07229f58cb686120f168276e434660e4358cc9cf3b0464210b04913e77", "f8a923a85cb099422ad5a2e345fe877bbc89a8a8b23235824a93488150e45f6e",]
+flake8 = [ "c7841163e2b576d435799169b78703ad6ac1bbb0f199994fc05f700b2a90ea37", "7253265f7abd8b313e3892944044a365e3f4ac3fcdcfb4298f55ee9ddf188ba0",]
+flake8-comprehensions = [ "e4ccf1627f75f192eb7fde640f5edb81c98d04b1390df9d4145ffd7710bb1ef2", "b83891fec0e680b07aa1fd92e53eb6993be29a0f3673a09badbe8da307c445e0",]
+geographiclib = [ "635da648fce80a57b81b28875d103dacf7deb12a3f5f7387ba7d39c51e096533",]
+geopy = [ "2947f914c89d665e86b19466cce3600f0d0574a54a17c7ba609058a0ef0b5f24", "9df0d61b431c51bcc47e64d16f9517dacfed10875f0dfc36cd8cb87c52fa9547",]
+httmock = [ "4696306d1ff835c3ca865fdef2684d7e130b4120cc00126f862ba4797b1602ac",]
+hypothesis = [ "ceb4d9b582184b041adc5647121fbafe3fcf49b7fbd218195d903c3fc6bc7916",]
+idna = [ "8c7309c718f94b3a625cb648ace320157ad16ff131ae0af362c9f21b80ef6ec4", "2c6a5de3089009e3da7c5dde64a141dbc8551d5b7f6cf4ed7c2568d0cc520a8f",]
+mccabe = [ "ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42", "dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f",]
+more-itertools = [ "a18d870ef2ffca2b8463c0070ad17b5978056f403fb64e3f15fe62a52db21cc0", "6703844a52d3588f951883005efcf555e49566a48afd4db4e965d69b883980d3", "2b6b9893337bfd9166bee6a62c2b0c9fe7735dcf85948b387ec8cba30e85d8e8",]
+mypy = [ "01cf289838f266ae7c6550c813181ee77d21eac9459dbf067e7a95a0a2db9721", "bc251cb31bc236d9fe4bcc442c994c45fff2541f7161ee52dc949741fe9ca3dd",]
+pillow = [ "f0d4433adce6075efd24fc0285135248b0b50f5a58129c7e552030e04fe45c7f", "81762cf5fca9a82b53b7b2d0e6b420e0f3b06167b97678c81d00470daa622d58", "b48401752496757e95304a46213c3155bc911ac884bed2e9b275ce1c1df3e293", "040144ba422216aecf7577484865ade90e1a475f867301c48bf9fbd7579efd76", "b6cf18f9e653a8077522bb3aa753a776b117e3e0cc872c25811cfdf1459491c2", "4d32c8e3623a61d6e29ccd024066cd1ba556555abfb4cd714155020e00107e3f", "438a3faf5f702c8d0f80b9f9f9b8382cfa048ca6a0d64ef71b86b563b0ee0359", "1cb38df69362af35c14d4a50123b63c7ff18ec9a6d4d5da629a6f19d05e16ba8", "4d8077fd649ac40a5c4165f2c22fa2a4ad18c668e271ecb2f9d849d1017a9313", "bb8adab1877e9213385cbb1adc297ed8337e01872c42a30cfaa66ff8c422779c", "f1f3bd92f8e12dc22884935a73c9f94c4d9bd0d34410c456540713d6b7832b8c", "6eca36905444c4b91fe61f1b9933a47a30480738a1dd26501ff67d94fc2bc112", "f7634d534662bbb08976db801ba27a112aee23e597eeaf09267b4575341e45bf", "eeb247f4f4d962942b3b555530b0c63b77473c7bfe475e51c6b75b7344b49ce3", "ea0091cd4100519cedfeea2c659f52291f535ac6725e2368bcf59e874f270efa", "e87cc1acbebf263f308a8494272c2d42016aa33c32bf14d209c81e1f65e11868", "3b4560c3891b05022c464b09121bd507c477505a4e19d703e1027a3a7c68d896", "7673e7473a13107059377c96c563aa36f73184c29d2926882e0a0210b779a1e7", "fe6931db24716a0845bd8c8915bd096b77c2a7043e6fc59ae9ca364fe816f08b", "f5f302db65e2e0ae96e26670818157640d3ca83a3054c290eff3631598dcf819", "9b66e968da9c4393f5795285528bc862c7b97b91251f31a08004a3c626d18114", "62ec7ae98357fcd46002c110bb7cad15fce532776f0cbe7ca1d44c49b837d49d", "d0dc1313dff48af64517cbbd85e046d6b477fbe5e9d69712801f024dcb08c62b", "00633bc2ec40313f4daf351855e506d296ec3c553f21b66720d0f1225ca84c6f", "16246261ff22368e5e32ad74d5ef40403ab6895171a7fc6d34f6c17cfc0f1943", "e52e8f675ba0b2b417fa98579e7286a41a8e23871f17f4793772f5aa884fea79", "6c7cab6a05351cf61e469937c49dbf3cdf5ffb3eeac71f8d22dc9be3507598d8", "e39142332541ed2884c257495504858b22c078a5d781059b07aba4c3a80d7551", "8554bbeb4218d9cfb1917c69e6f2d2ad0be9b18a775d2162547edf992e1f5f1f", "2400e122f7b21d9801798207e424cbe1f716cee7314cd0c8963fdb6fc564b5fb", "a00edb2dec0035e98ac3ec768086f0b06dfabb4ad308592ede364ef573692f55", "fdd374c02e8bb2d6468a85be50ea66e1c4ef9e809974c30d8576728473a6ed03", "df5863a21f91de5ecdf7d32a32f406dd9867ebb35d41033b8bd9607a21887599", "472a124c640bde4d5468f6991c9fa7e30b723d84ac4195a77c6ab6aea30f2b9c", "cee9bc75bff455d317b6947081df0824a8f118de2786dc3d74a3503fd631f4ef", "2ee6364b270b56a49e8b8a51488e847ab130adc1220c171bed6818c0d4742455", "03514478db61b034fc5d38b9bf060f994e5916776e93f02e59732a8270069c61", "74e2ebfd19c16c28ad43b8a28ff73b904ed382ea4875188838541751986e8c9a", "e6dd55d5d94b9e36929325dd0c9ab85bfde84a5fc35947c334c32af1af668944", "f42a87cbf50e905f49f053c0b1fb86c911c730624022bf44c8857244fc4cdaca", "d5bf527ed83617edd1855a5c923eeeaf68bcb9ac0ceb28e3f19b575b3a424984", "41374a6afb3f44794410dab54a0d7175e6209a5a02d407119c81083f1a4c1841", "c8a4b39ba380b57a31a4b5449a9d257b1302d8bc4799767e645dcee25725efe1",]
+pluggy = [ "d345c8fe681115900d6da8d048ba67c25df42973bda370783cd58826442dcd7c", "e160a7fcf25762bb60efc7e171d4497ff1d8d2d75a3d0df7a21b76821ecbf5c5", "7f8ae7f5bdf75671a718d2daf0a64b7885f74510bcd98b1a0bb420eb9a9d0cff",]
+py = [ "983f77f3331356039fdd792e9220b7b8ee1aa6bd2b25f567a963ff1de5a64f6a", "29c9fab495d7528e80ba1e343b958684f4ace687327e6f789a94bf3d1915f881",]
+pycodestyle = [ "6c4245ade1edfad79c3446fadfc96b0de2759662dc29d07d80a6f27ad1ca6ba9", "682256a5b318149ca0d2a9185d365d8864a768a28db66a84a2ea946bcc426766",]
+pyflakes = [ "08bd6a50edf8cffa9fa09a463063c425ecaaf10d1eb0335a7e8b1401aef89e6f", "8d616a382f243dbf19b54743f280b80198be0bca3a5396f1d2e1fca6223e8805",]
+pytest = [ "26838b2bc58620e01675485491504c3aa7ee0faf335c37fcd5f8731ca4319591", "32c49a69566aa7c333188149ad48b58ac11a426d5352ea3d8f6ce843f88199cb",]
+pytest-cov = [ "890fe5565400902b0c78b5357004aab1c814115894f4f21370e2433256a3eeec", "03aa752cf11db41d281ea1d807d954c4eda35cfa1b21d6971966cc041bbf6e2d",]
+pytest-mock = [ "53801e621223d34724926a5c98bd90e8e417ce35264365d39d6c896388dcc928", "d89a8209d722b8307b5e351496830d5cc5e192336003a485443ae9adeb7dd4c0",]
+pytest-random-order = [ "44cd0e1ae035d91b927f61a4c23c7949d295e57958d168f2e950b1d322089def",]
+pytest-sugar = [ "ab8cc42faf121344a4e9b13f39a51257f26f410e416c52ea11078cdd00d98a2c",]
+requests = [ "6a1b267aa90cac58ac3a765d067950e7dbbf75b1da07e895d1f594193a40a38b", "9c443e7324ba5b85070c4a818ade28bfabedf16ea10206da1132edaa6dda237e",]
+six = [ "832dc0e10feb1aa2c68dcc57dbb658f1c7e65b9b61af69048abc87a2db00a0eb", "70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9",]
+termcolor = [ "1d6d69ce66211143803fbc56652b41d73b4a400a2891d7bf7a1cdf4c02de613b",]
+tox = [ "9ee7de958a43806402a38c0d2aa07fa8553f4d2c20a15b140e9f771c2afeade0", "96efa09710a3daeeb845561ebbe1497641d9cef2ee0aea30db6969058b2bda2f",]
+typed-ast = [ "0948004fa228ae071054f5208840a1e88747a357ec1101c17217bfe99b299d58", "25d8feefe27eb0303b73545416b13d108c6067b846b543738a25ff304824ed9a", "c05b41bc1deade9f90ddc5d988fe506208019ebba9f2578c622516fd201f5863", "519425deca5c2b2bdac49f77b2c5625781abbaf9a809d727d3a5596b30bb4ded", "6de012d2b166fe7a4cdf505eee3aaa12192f7ba365beeefaca4ec10e31241a85", "79b91ebe5a28d349b6d0d323023350133e927b4de5b651a8aa2db69c761420c6", "a8034021801bc0440f2e027c354b4eafd95891b573e12ff0418dec385c76785c", "f19f2a4f547505fe9072e15f6f4ae714af51b5a681a97f187971f50c283193b6", "c9b060bd1e5a26ab6e8267fd46fc9e02b54eb15fffb16d112d4c7b1c12987559", "2e214b72168ea0275efd6c884b114ab42e316de3ffa125b267e732ed2abda892", "bc978ac17468fe868ee589c795d06777f75496b1ed576d308002c8a5756fb9ea", "edb04bdd45bfd76c8292c4d9654568efaedf76fe78eb246dde69bdb13b2dad87", "668d0cec391d9aed1c6a388b0d5b97cd22e6073eaa5fbaa6d2946603b4871efe", "29464a177d56e4e055b5f7b629935af7f49c196be47528cc94e0a7bf83fbc2b9", "8550177fa5d4c1f09b5e5f524411c44633c80ec69b24e0e98906dd761941ca46", "3e0d5e48e3a23e9a4d1a9f698e32a542a4a288c871d33ed8df1b092a40f3a0f9", "68ba70684990f59497680ff90d18e756a47bf4863c604098f10de9716b2c0bdd", "57fe287f0cdd9ceaf69e7b71a2e94a24b5d268b35df251a88fef5cc241bf73aa",]
+urllib3 = [ "06330f386d6e4b195fbfc736b297f58c5a892e4440e54d294d7004e3a9bbea1b", "cc44da8e1145637334317feebd728bd869a35285b93cbb4cca2577da7e62db4f",]
+virtualenv = [ "2ce32cd126117ce2c539f0134eb89de91a8413a29baac49cbab3eb50e2026669", "ca07b4c0b54e14a91af9f34d0919790b016923d157afda5efdde55c96718f752",]
diff --git a/uv/spec/fixtures/poetry_locks/private_secondary_source.lock b/uv/spec/fixtures/poetry_locks/private_secondary_source.lock
new file mode 100644
index 00000000000..c0b85be171f
--- /dev/null
+++ b/uv/spec/fixtures/poetry_locks/private_secondary_source.lock
@@ -0,0 +1,90 @@
+[[package]]
+name = "docutils"
+version = "0.18.1"
+description = "Docutils -- Python Documentation Utilities"
+category = "main"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
+
+[[package]]
+name = "enum34"
+version = "1.1.10"
+description = "Python 3.4 Enum backported to 3.3, 3.2, 3.1, 2.7, 2.6, 2.5, and 2.4"
+category = "main"
+optional = false
+python-versions = "*"
+
+[[package]]
+name = "lockfile"
+version = "0.12.2"
+description = "Platform-independent file locking module"
+category = "main"
+optional = false
+python-versions = "*"
+
+[[package]]
+name = "luigi"
+version = "2.8.8"
+description = "Workflow mgmgt + task scheduling + dependency resolution"
+category = "main"
+optional = false
+python-versions = "*"
+
+[package.dependencies]
+enum34 = ">1.1.0"
+python-daemon = "<2.2.0"
+python-dateutil = ">=2.7.5,<3"
+tornado = ">=4.0,<5"
+
+[package.extras]
+prometheus = ["prometheus-client (==0.5.0)"]
+toml = ["toml (<2.0.0)"]
+
+[package.source]
+type = "legacy"
+url = "http://localhost:8080/simple"
+reference = "custom"
+
+[[package]]
+name = "python-daemon"
+version = "2.1.2"
+description = "Library to implement a well-behaved Unix daemon process."
+category = "main"
+optional = false
+python-versions = "*"
+
+[package.dependencies]
+docutils = "*"
+lockfile = ">=0.10"
+
+[[package]]
+name = "python-dateutil"
+version = "2.8.2"
+description = "Extensions to the standard Python datetime module"
+category = "main"
+optional = false
+python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7"
+
+[package.dependencies]
+six = ">=1.5"
+
+[[package]]
+name = "six"
+version = "1.16.0"
+description = "Python 2 and 3 compatibility utilities"
+category = "main"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*"
+
+[[package]]
+name = "tornado"
+version = "4.5.3"
+description = "Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed."
+category = "main"
+optional = false
+python-versions = "*"
+
+[metadata]
+lock-version = "1.1"
+python-versions = "^3.7"
+content-hash = "6217e8de9f5f3e12db2d2155d2e878cecb9a590ac6d1b19c85df9f64d3d57853"
diff --git a/uv/spec/fixtures/poetry_locks/python_2.lock b/uv/spec/fixtures/poetry_locks/python_2.lock
new file mode 100644
index 00000000000..d2519eb6b22
--- /dev/null
+++ b/uv/spec/fixtures/poetry_locks/python_2.lock
@@ -0,0 +1,56 @@
+[[package]]
+category = "main"
+description = "Python package for providing Mozilla's CA Bundle."
+name = "certifi"
+optional = false
+python-versions = "*"
+version = "2018.10.15"
+
+[[package]]
+category = "main"
+description = "Universal encoding detector for Python 2 and 3"
+name = "chardet"
+optional = false
+python-versions = "*"
+version = "3.0.4"
+
+[[package]]
+category = "main"
+description = "Internationalized Domain Names in Applications (IDNA)"
+name = "idna"
+optional = false
+python-versions = "*"
+version = "2.5"
+
+[[package]]
+category = "main"
+description = "Python HTTP for Humans."
+name = "requests"
+optional = false
+python-versions = "*"
+version = "2.18.0"
+
+[package.dependencies]
+certifi = ">=2017.4.17"
+chardet = ">=3.0.2,<3.1.0"
+idna = ">=2.5,<2.6"
+urllib3 = ">=1.21.1,<1.22"
+
+[[package]]
+category = "main"
+description = "HTTP library with thread-safe connection pooling, file post, and more."
+name = "urllib3"
+optional = false
+python-versions = "*"
+version = "1.21.1"
+
+[metadata]
+content-hash = "985ef2361aa7ef32655a050b528bb2c540e986a1827479353dc42cb7a2b5a3bc"
+python-versions = "~2.6 || ^2.7"
+
+[metadata.hashes]
+certifi = ["339dc09518b07e2fa7eda5450740925974815557727d6bd35d319c1524a04a4c", "6d58c986d22b038c8c0df30d639f23a3e6d172a05c3583e766f4c0b785c0986a"]
+chardet = ["84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae", "fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"]
+idna = ["3cb5ce08046c4e3a560fc02f138d0ac63e00f8ce5901a56b32ec8b7994082aab", "cc19709fd6d0cbfed39ea875d29ba6d4e22c0cebc510a76d6302a28385e8bb70"]
+requests = ["5e88d64aa56ac0fda54e77fb9762ebc65879e171b746d5479a33c4082519d6c6", "cd0189f962787284bff715fddaad478eb4d9c15aa167bd64e52ea0f661e7ea5c"]
+urllib3 = ["8ed6d5c1ff9d6ba84677310060d6a3a78ca3072ce0684cb3c645023009c114b1", "b14486978518ca0901a76ba973d7821047409d7f726f22156b24e83fd71382a5"]
diff --git a/uv/spec/fixtures/poetry_locks/python_310.lock b/uv/spec/fixtures/poetry_locks/python_310.lock
new file mode 100644
index 00000000000..8acd3f85922
--- /dev/null
+++ b/uv/spec/fixtures/poetry_locks/python_310.lock
@@ -0,0 +1,80 @@
+[[package]]
+name = "certifi"
+version = "2022.9.24"
+description = "Python package for providing Mozilla's CA Bundle."
+category = "main"
+optional = false
+python-versions = ">=3.6"
+
+[[package]]
+name = "chardet"
+version = "3.0.4"
+description = "Universal encoding detector for Python 2 and 3"
+category = "main"
+optional = false
+python-versions = "*"
+
+[[package]]
+name = "idna"
+version = "2.5"
+description = "Internationalized Domain Names in Applications (IDNA)"
+category = "main"
+optional = false
+python-versions = "*"
+
+[[package]]
+name = "requests"
+version = "2.18.0"
+description = "Python HTTP for Humans."
+category = "main"
+optional = false
+python-versions = "*"
+
+[package.dependencies]
+certifi = ">=2017.4.17"
+chardet = ">=3.0.2,<3.1.0"
+idna = ">=2.5,<2.6"
+urllib3 = ">=1.21.1,<1.22"
+
+[package.extras]
+security = ["cryptography (>=1.3.4)", "idna (>=2.0.0)", "pyOpenSSL (>=0.14)"]
+socks = ["PySocks (>=1.5.6,!=1.5.7)", "win-inet-pton"]
+
+[[package]]
+name = "urllib3"
+version = "1.21.1"
+description = "HTTP library with thread-safe connection pooling, file post, and more."
+category = "main"
+optional = false
+python-versions = "*"
+
+[package.extras]
+secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress", "pyOpenSSL (>=0.14)"]
+socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"]
+
+[metadata]
+lock-version = "1.1"
+python-versions = "3.10.7"
+content-hash = "f56ecb5b0d42f75b0c0992902acd1847a2f182b4088da95353f9bfbecc3308eb"
+
+[metadata.files]
+certifi = [
+ {file = "certifi-2022.9.24-py3-none-any.whl", hash = "sha256:90c1a32f1d68f940488354e36370f6cca89f0f106db09518524c88d6ed83f382"},
+ {file = "certifi-2022.9.24.tar.gz", hash = "sha256:0d9c601124e5a6ba9712dbc60d9c53c21e34f5f641fe83002317394311bdce14"},
+]
+chardet = [
+ {file = "chardet-3.0.4-py2.py3-none-any.whl", hash = "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"},
+ {file = "chardet-3.0.4.tar.gz", hash = "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae"},
+]
+idna = [
+ {file = "idna-2.5-py2.py3-none-any.whl", hash = "sha256:cc19709fd6d0cbfed39ea875d29ba6d4e22c0cebc510a76d6302a28385e8bb70"},
+ {file = "idna-2.5.tar.gz", hash = "sha256:3cb5ce08046c4e3a560fc02f138d0ac63e00f8ce5901a56b32ec8b7994082aab"},
+]
+requests = [
+ {file = "requests-2.18.0-py2.py3-none-any.whl", hash = "sha256:5e88d64aa56ac0fda54e77fb9762ebc65879e171b746d5479a33c4082519d6c6"},
+ {file = "requests-2.18.0.tar.gz", hash = "sha256:cd0189f962787284bff715fddaad478eb4d9c15aa167bd64e52ea0f661e7ea5c"},
+]
+urllib3 = [
+ {file = "urllib3-1.21.1-py2.py3-none-any.whl", hash = "sha256:8ed6d5c1ff9d6ba84677310060d6a3a78ca3072ce0684cb3c645023009c114b1"},
+ {file = "urllib3-1.21.1.tar.gz", hash = "sha256:b14486978518ca0901a76ba973d7821047409d7f726f22156b24e83fd71382a5"},
+]
diff --git a/uv/spec/fixtures/poetry_locks/python_39.lock b/uv/spec/fixtures/poetry_locks/python_39.lock
new file mode 100644
index 00000000000..4be7a7979f2
--- /dev/null
+++ b/uv/spec/fixtures/poetry_locks/python_39.lock
@@ -0,0 +1,367 @@
+# This file is automatically @generated by Poetry 1.6.1 and should not be changed by hand.
+
+[[package]]
+name = "asgiref"
+version = "3.8.1"
+description = "ASGI specs, helper code, and adapters"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "asgiref-3.8.1-py3-none-any.whl", hash = "sha256:3e1e3ecc849832fe52ccf2cb6686b7a55f82bb1d6aee72a58826471390335e47"},
+ {file = "asgiref-3.8.1.tar.gz", hash = "sha256:c343bd80a0bec947a9860adb4c432ffa7db769836c64238fc34bdc3fec84d590"},
+]
+
+[package.dependencies]
+typing-extensions = {version = ">=4", markers = "python_version < \"3.11\""}
+
+[package.extras]
+tests = ["mypy (>=0.800)", "pytest", "pytest-asyncio"]
+
+[[package]]
+name = "atomicwrites"
+version = "1.4.1"
+description = "Atomic file writes."
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+files = [
+ {file = "atomicwrites-1.4.1.tar.gz", hash = "sha256:81b2c9071a49367a7f770170e5eec8cb66567cfbbc8c73d20ce5ca4a8d71cf11"},
+]
+
+[[package]]
+name = "attrs"
+version = "25.1.0"
+description = "Classes Without Boilerplate"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "attrs-25.1.0-py3-none-any.whl", hash = "sha256:c75a69e28a550a7e93789579c22aa26b0f5b83b75dc4e08fe092980051e1090a"},
+ {file = "attrs-25.1.0.tar.gz", hash = "sha256:1c97078a80c814273a76b2a298a932eb681c87415c11dee0a6921de7f1b02c3e"},
+]
+
+[package.extras]
+benchmark = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-codspeed", "pytest-mypy-plugins", "pytest-xdist[psutil]"]
+cov = ["cloudpickle", "coverage[toml] (>=5.3)", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"]
+dev = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pre-commit-uv", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"]
+docs = ["cogapp", "furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier (<24.7)"]
+tests = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"]
+tests-mypy = ["mypy (>=1.11.1)", "pytest-mypy-plugins"]
+
+[[package]]
+name = "certifi"
+version = "2025.1.31"
+description = "Python package for providing Mozilla's CA Bundle."
+optional = false
+python-versions = ">=3.6"
+files = [
+ {file = "certifi-2025.1.31-py3-none-any.whl", hash = "sha256:ca78db4565a652026a4db2bcdf68f2fb589ea80d0be70e03929ed730746b84fe"},
+ {file = "certifi-2025.1.31.tar.gz", hash = "sha256:3d5da6925056f6f18f119200434a4780a94263f10d1c21d032a6f6b2baa20651"},
+]
+
+[[package]]
+name = "charset-normalizer"
+version = "3.4.1"
+description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet."
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "charset_normalizer-3.4.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:91b36a978b5ae0ee86c394f5a54d6ef44db1de0815eb43de826d41d21e4af3de"},
+ {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7461baadb4dc00fd9e0acbe254e3d7d2112e7f92ced2adc96e54ef6501c5f176"},
+ {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e218488cd232553829be0664c2292d3af2eeeb94b32bea483cf79ac6a694e037"},
+ {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:80ed5e856eb7f30115aaf94e4a08114ccc8813e6ed1b5efa74f9f82e8509858f"},
+ {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b010a7a4fd316c3c484d482922d13044979e78d1861f0e0650423144c616a46a"},
+ {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4532bff1b8421fd0a320463030c7520f56a79c9024a4e88f01c537316019005a"},
+ {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d973f03c0cb71c5ed99037b870f2be986c3c05e63622c017ea9816881d2dd247"},
+ {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:3a3bd0dcd373514dcec91c411ddb9632c0d7d92aed7093b8c3bbb6d69ca74408"},
+ {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:d9c3cdf5390dcd29aa8056d13e8e99526cda0305acc038b96b30352aff5ff2bb"},
+ {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:2bdfe3ac2e1bbe5b59a1a63721eb3b95fc9b6817ae4a46debbb4e11f6232428d"},
+ {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:eab677309cdb30d047996b36d34caeda1dc91149e4fdca0b1a039b3f79d9a807"},
+ {file = "charset_normalizer-3.4.1-cp310-cp310-win32.whl", hash = "sha256:c0429126cf75e16c4f0ad00ee0eae4242dc652290f940152ca8c75c3a4b6ee8f"},
+ {file = "charset_normalizer-3.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:9f0b8b1c6d84c8034a44893aba5e767bf9c7a211e313a9605d9c617d7083829f"},
+ {file = "charset_normalizer-3.4.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:8bfa33f4f2672964266e940dd22a195989ba31669bd84629f05fab3ef4e2d125"},
+ {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:28bf57629c75e810b6ae989f03c0828d64d6b26a5e205535585f96093e405ed1"},
+ {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f08ff5e948271dc7e18a35641d2f11a4cd8dfd5634f55228b691e62b37125eb3"},
+ {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:234ac59ea147c59ee4da87a0c0f098e9c8d169f4dc2a159ef720f1a61bbe27cd"},
+ {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd4ec41f914fa74ad1b8304bbc634b3de73d2a0889bd32076342a573e0779e00"},
+ {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eea6ee1db730b3483adf394ea72f808b6e18cf3cb6454b4d86e04fa8c4327a12"},
+ {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c96836c97b1238e9c9e3fe90844c947d5afbf4f4c92762679acfe19927d81d77"},
+ {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:4d86f7aff21ee58f26dcf5ae81a9addbd914115cdebcbb2217e4f0ed8982e146"},
+ {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:09b5e6733cbd160dcc09589227187e242a30a49ca5cefa5a7edd3f9d19ed53fd"},
+ {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:5777ee0881f9499ed0f71cc82cf873d9a0ca8af166dfa0af8ec4e675b7df48e6"},
+ {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:237bdbe6159cff53b4f24f397d43c6336c6b0b42affbe857970cefbb620911c8"},
+ {file = "charset_normalizer-3.4.1-cp311-cp311-win32.whl", hash = "sha256:8417cb1f36cc0bc7eaba8ccb0e04d55f0ee52df06df3ad55259b9a323555fc8b"},
+ {file = "charset_normalizer-3.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:d7f50a1f8c450f3925cb367d011448c39239bb3eb4117c36a6d354794de4ce76"},
+ {file = "charset_normalizer-3.4.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:73d94b58ec7fecbc7366247d3b0b10a21681004153238750bb67bd9012414545"},
+ {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dad3e487649f498dd991eeb901125411559b22e8d7ab25d3aeb1af367df5efd7"},
+ {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c30197aa96e8eed02200a83fba2657b4c3acd0f0aa4bdc9f6c1af8e8962e0757"},
+ {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2369eea1ee4a7610a860d88f268eb39b95cb588acd7235e02fd5a5601773d4fa"},
+ {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc2722592d8998c870fa4e290c2eec2c1569b87fe58618e67d38b4665dfa680d"},
+ {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffc9202a29ab3920fa812879e95a9e78b2465fd10be7fcbd042899695d75e616"},
+ {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:804a4d582ba6e5b747c625bf1255e6b1507465494a40a2130978bda7b932c90b"},
+ {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:0f55e69f030f7163dffe9fd0752b32f070566451afe180f99dbeeb81f511ad8d"},
+ {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:c4c3e6da02df6fa1410a7680bd3f63d4f710232d3139089536310d027950696a"},
+ {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:5df196eb874dae23dcfb968c83d4f8fdccb333330fe1fc278ac5ceeb101003a9"},
+ {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e358e64305fe12299a08e08978f51fc21fac060dcfcddd95453eabe5b93ed0e1"},
+ {file = "charset_normalizer-3.4.1-cp312-cp312-win32.whl", hash = "sha256:9b23ca7ef998bc739bf6ffc077c2116917eabcc901f88da1b9856b210ef63f35"},
+ {file = "charset_normalizer-3.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:6ff8a4a60c227ad87030d76e99cd1698345d4491638dfa6673027c48b3cd395f"},
+ {file = "charset_normalizer-3.4.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:aabfa34badd18f1da5ec1bc2715cadc8dca465868a4e73a0173466b688f29dda"},
+ {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22e14b5d70560b8dd51ec22863f370d1e595ac3d024cb8ad7d308b4cd95f8313"},
+ {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8436c508b408b82d87dc5f62496973a1805cd46727c34440b0d29d8a2f50a6c9"},
+ {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2d074908e1aecee37a7635990b2c6d504cd4766c7bc9fc86d63f9c09af3fa11b"},
+ {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:955f8851919303c92343d2f66165294848d57e9bba6cf6e3625485a70a038d11"},
+ {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:44ecbf16649486d4aebafeaa7ec4c9fed8b88101f4dd612dcaf65d5e815f837f"},
+ {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:0924e81d3d5e70f8126529951dac65c1010cdf117bb75eb02dd12339b57749dd"},
+ {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:2967f74ad52c3b98de4c3b32e1a44e32975e008a9cd2a8cc8966d6a5218c5cb2"},
+ {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:c75cb2a3e389853835e84a2d8fb2b81a10645b503eca9bcb98df6b5a43eb8886"},
+ {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:09b26ae6b1abf0d27570633b2b078a2a20419c99d66fb2823173d73f188ce601"},
+ {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:fa88b843d6e211393a37219e6a1c1df99d35e8fd90446f1118f4216e307e48cd"},
+ {file = "charset_normalizer-3.4.1-cp313-cp313-win32.whl", hash = "sha256:eb8178fe3dba6450a3e024e95ac49ed3400e506fd4e9e5c32d30adda88cbd407"},
+ {file = "charset_normalizer-3.4.1-cp313-cp313-win_amd64.whl", hash = "sha256:b1ac5992a838106edb89654e0aebfc24f5848ae2547d22c2c3f66454daa11971"},
+ {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f30bf9fd9be89ecb2360c7d94a711f00c09b976258846efe40db3d05828e8089"},
+ {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:97f68b8d6831127e4787ad15e6757232e14e12060bec17091b85eb1486b91d8d"},
+ {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7974a0b5ecd505609e3b19742b60cee7aa2aa2fb3151bc917e6e2646d7667dcf"},
+ {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc54db6c8593ef7d4b2a331b58653356cf04f67c960f584edb7c3d8c97e8f39e"},
+ {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:311f30128d7d333eebd7896965bfcfbd0065f1716ec92bd5638d7748eb6f936a"},
+ {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:7d053096f67cd1241601111b698f5cad775f97ab25d81567d3f59219b5f1adbd"},
+ {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_i686.whl", hash = "sha256:807f52c1f798eef6cf26beb819eeb8819b1622ddfeef9d0977a8502d4db6d534"},
+ {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_ppc64le.whl", hash = "sha256:dccbe65bd2f7f7ec22c4ff99ed56faa1e9f785482b9bbd7c717e26fd723a1d1e"},
+ {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_s390x.whl", hash = "sha256:2fb9bd477fdea8684f78791a6de97a953c51831ee2981f8e4f583ff3b9d9687e"},
+ {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:01732659ba9b5b873fc117534143e4feefecf3b2078b0a6a2e925271bb6f4cfa"},
+ {file = "charset_normalizer-3.4.1-cp37-cp37m-win32.whl", hash = "sha256:7a4f97a081603d2050bfaffdefa5b02a9ec823f8348a572e39032caa8404a487"},
+ {file = "charset_normalizer-3.4.1-cp37-cp37m-win_amd64.whl", hash = "sha256:7b1bef6280950ee6c177b326508f86cad7ad4dff12454483b51d8b7d673a2c5d"},
+ {file = "charset_normalizer-3.4.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:ecddf25bee22fe4fe3737a399d0d177d72bc22be6913acfab364b40bce1ba83c"},
+ {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c60ca7339acd497a55b0ea5d506b2a2612afb2826560416f6894e8b5770d4a9"},
+ {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b7b2d86dd06bfc2ade3312a83a5c364c7ec2e3498f8734282c6c3d4b07b346b8"},
+ {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dd78cfcda14a1ef52584dbb008f7ac81c1328c0f58184bf9a84c49c605002da6"},
+ {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e27f48bcd0957c6d4cb9d6fa6b61d192d0b13d5ef563e5f2ae35feafc0d179c"},
+ {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:01ad647cdd609225c5350561d084b42ddf732f4eeefe6e678765636791e78b9a"},
+ {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:619a609aa74ae43d90ed2e89bdd784765de0a25ca761b93e196d938b8fd1dbbd"},
+ {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:89149166622f4db9b4b6a449256291dc87a99ee53151c74cbd82a53c8c2f6ccd"},
+ {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:7709f51f5f7c853f0fb938bcd3bc59cdfdc5203635ffd18bf354f6967ea0f824"},
+ {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:345b0426edd4e18138d6528aed636de7a9ed169b4aaf9d61a8c19e39d26838ca"},
+ {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:0907f11d019260cdc3f94fbdb23ff9125f6b5d1039b76003b5b0ac9d6a6c9d5b"},
+ {file = "charset_normalizer-3.4.1-cp38-cp38-win32.whl", hash = "sha256:ea0d8d539afa5eb2728aa1932a988a9a7af94f18582ffae4bc10b3fbdad0626e"},
+ {file = "charset_normalizer-3.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:329ce159e82018d646c7ac45b01a430369d526569ec08516081727a20e9e4af4"},
+ {file = "charset_normalizer-3.4.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:b97e690a2118911e39b4042088092771b4ae3fc3aa86518f84b8cf6888dbdb41"},
+ {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:78baa6d91634dfb69ec52a463534bc0df05dbd546209b79a3880a34487f4b84f"},
+ {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1a2bc9f351a75ef49d664206d51f8e5ede9da246602dc2d2726837620ea034b2"},
+ {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:75832c08354f595c760a804588b9357d34ec00ba1c940c15e31e96d902093770"},
+ {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0af291f4fe114be0280cdd29d533696a77b5b49cfde5467176ecab32353395c4"},
+ {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0167ddc8ab6508fe81860a57dd472b2ef4060e8d378f0cc555707126830f2537"},
+ {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:2a75d49014d118e4198bcee5ee0a6f25856b29b12dbf7cd012791f8a6cc5c496"},
+ {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:363e2f92b0f0174b2f8238240a1a30142e3db7b957a5dd5689b0e75fb717cc78"},
+ {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:ab36c8eb7e454e34e60eb55ca5d241a5d18b2c6244f6827a30e451c42410b5f7"},
+ {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:4c0907b1928a36d5a998d72d64d8eaa7244989f7aaaf947500d3a800c83a3fd6"},
+ {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:04432ad9479fa40ec0f387795ddad4437a2b50417c69fa275e212933519ff294"},
+ {file = "charset_normalizer-3.4.1-cp39-cp39-win32.whl", hash = "sha256:3bed14e9c89dcb10e8f3a29f9ccac4955aebe93c71ae803af79265c9ca5644c5"},
+ {file = "charset_normalizer-3.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:49402233c892a461407c512a19435d1ce275543138294f7ef013f0b63d5d3765"},
+ {file = "charset_normalizer-3.4.1-py3-none-any.whl", hash = "sha256:d98b1668f06378c6dbefec3b92299716b931cd4e6061f3c875a71ced1780ab85"},
+ {file = "charset_normalizer-3.4.1.tar.gz", hash = "sha256:44251f18cd68a75b56585dd00dae26183e102cd5e0f9f1466e6df5da2ed64ea3"},
+]
+
+[[package]]
+name = "colorama"
+version = "0.4.6"
+description = "Cross-platform colored terminal text."
+optional = false
+python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
+files = [
+ {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"},
+ {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
+]
+
+[[package]]
+name = "django"
+version = "3.0"
+description = "A high-level Python Web framework that encourages rapid development and clean, pragmatic design."
+optional = false
+python-versions = ">=3.6"
+files = [
+ {file = "Django-3.0-py3-none-any.whl", hash = "sha256:6f857bd4e574442ba35a7172f1397b303167dae964cf18e53db5e85fe248d000"},
+ {file = "Django-3.0.tar.gz", hash = "sha256:d98c9b6e5eed147bc51f47c014ff6826bd1ab50b166956776ee13db5a58804ae"},
+]
+
+[package.dependencies]
+asgiref = ">=3.2,<4.0"
+pytz = "*"
+sqlparse = ">=0.2.2"
+
+[package.extras]
+argon2 = ["argon2-cffi (>=16.1.0)"]
+bcrypt = ["bcrypt"]
+
+[[package]]
+name = "idna"
+version = "3.10"
+description = "Internationalized Domain Names in Applications (IDNA)"
+optional = false
+python-versions = ">=3.6"
+files = [
+ {file = "idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"},
+ {file = "idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9"},
+]
+
+[package.extras]
+all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2)"]
+
+[[package]]
+name = "more-itertools"
+version = "10.6.0"
+description = "More routines for operating on iterables, beyond itertools"
+optional = false
+python-versions = ">=3.9"
+files = [
+ {file = "more-itertools-10.6.0.tar.gz", hash = "sha256:2cd7fad1009c31cc9fb6a035108509e6547547a7a738374f10bd49a09eb3ee3b"},
+ {file = "more_itertools-10.6.0-py3-none-any.whl", hash = "sha256:6eb054cb4b6db1473f6e15fcc676a08e4732548acd47c708f0e179c2c7c01e89"},
+]
+
+[[package]]
+name = "packaging"
+version = "24.2"
+description = "Core utilities for Python packages"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "packaging-24.2-py3-none-any.whl", hash = "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759"},
+ {file = "packaging-24.2.tar.gz", hash = "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f"},
+]
+
+[[package]]
+name = "pluggy"
+version = "0.13.1"
+description = "plugin and hook calling mechanisms for python"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+files = [
+ {file = "pluggy-0.13.1-py2.py3-none-any.whl", hash = "sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d"},
+ {file = "pluggy-0.13.1.tar.gz", hash = "sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0"},
+]
+
+[package.extras]
+dev = ["pre-commit", "tox"]
+
+[[package]]
+name = "py"
+version = "1.11.0"
+description = "library with cross-python path, ini-parsing, io, code, log facilities"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
+files = [
+ {file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"},
+ {file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"},
+]
+
+[[package]]
+name = "pytest"
+version = "5.4.3"
+description = "pytest: simple powerful testing with Python"
+optional = false
+python-versions = ">=3.5"
+files = [
+ {file = "pytest-5.4.3-py3-none-any.whl", hash = "sha256:5c0db86b698e8f170ba4582a492248919255fcd4c79b1ee64ace34301fb589a1"},
+ {file = "pytest-5.4.3.tar.gz", hash = "sha256:7979331bfcba207414f5e1263b5a0f8f521d0f457318836a7355531ed1a4c7d8"},
+]
+
+[package.dependencies]
+atomicwrites = {version = ">=1.0", markers = "sys_platform == \"win32\""}
+attrs = ">=17.4.0"
+colorama = {version = "*", markers = "sys_platform == \"win32\""}
+more-itertools = ">=4.0.0"
+packaging = "*"
+pluggy = ">=0.12,<1.0"
+py = ">=1.5.0"
+wcwidth = "*"
+
+[package.extras]
+checkqa-mypy = ["mypy (==v0.761)"]
+testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "requests", "xmlschema"]
+
+[[package]]
+name = "pytz"
+version = "2025.1"
+description = "World timezone definitions, modern and historical"
+optional = false
+python-versions = "*"
+files = [
+ {file = "pytz-2025.1-py2.py3-none-any.whl", hash = "sha256:89dd22dca55b46eac6eda23b2d72721bf1bdfef212645d81513ef5d03038de57"},
+ {file = "pytz-2025.1.tar.gz", hash = "sha256:c2db42be2a2518b28e65f9207c4d05e6ff547d1efa4086469ef855e4ab70178e"},
+]
+
+[[package]]
+name = "requests"
+version = "2.32.3"
+description = "Python HTTP for Humans."
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"},
+ {file = "requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760"},
+]
+
+[package.dependencies]
+certifi = ">=2017.4.17"
+charset-normalizer = ">=2,<4"
+idna = ">=2.5,<4"
+urllib3 = ">=1.21.1,<3"
+
+[package.extras]
+socks = ["PySocks (>=1.5.6,!=1.5.7)"]
+use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"]
+
+[[package]]
+name = "sqlparse"
+version = "0.5.3"
+description = "A non-validating SQL parser."
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "sqlparse-0.5.3-py3-none-any.whl", hash = "sha256:cf2196ed3418f3ba5de6af7e82c694a9fbdbfecccdfc72e281548517081f16ca"},
+ {file = "sqlparse-0.5.3.tar.gz", hash = "sha256:09f67787f56a0b16ecdbde1bfc7f5d9c3371ca683cfeaa8e6ff60b4807ec9272"},
+]
+
+[package.extras]
+dev = ["build", "hatch"]
+doc = ["sphinx"]
+
+[[package]]
+name = "typing-extensions"
+version = "4.12.2"
+description = "Backported and Experimental Type Hints for Python 3.8+"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"},
+ {file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"},
+]
+
+[[package]]
+name = "urllib3"
+version = "2.3.0"
+description = "HTTP library with thread-safe connection pooling, file post, and more."
+optional = false
+python-versions = ">=3.9"
+files = [
+ {file = "urllib3-2.3.0-py3-none-any.whl", hash = "sha256:1cee9ad369867bfdbbb48b7dd50374c0967a0bb7710050facf0dd6911440e3df"},
+ {file = "urllib3-2.3.0.tar.gz", hash = "sha256:f8c5449b3cf0861679ce7e0503c7b44b5ec981bec0d1d3795a07f1ba96f0204d"},
+]
+
+[package.extras]
+brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"]
+h2 = ["h2 (>=4,<5)"]
+socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"]
+zstd = ["zstandard (>=0.18.0)"]
+
+[[package]]
+name = "wcwidth"
+version = "0.2.13"
+description = "Measures the displayed width of unicode strings in a terminal"
+optional = false
+python-versions = "*"
+files = [
+ {file = "wcwidth-0.2.13-py2.py3-none-any.whl", hash = "sha256:3da69048e4540d84af32131829ff948f1e022c1c6bdb8d6102117aac784f6859"},
+ {file = "wcwidth-0.2.13.tar.gz", hash = "sha256:72ea0c06399eb286d978fdedb6923a9eb47e1c486ce63e9b4e64fc18303972b5"},
+]
+
+[metadata]
+lock-version = "2.0"
+python-versions = "3.9.21"
+content-hash = "e58ac67df813f535af4a927e591e8d5312886b8a9518da14e58a8c15defa18fd"
diff --git a/uv/spec/fixtures/poetry_locks/python_lower_bound.toml b/uv/spec/fixtures/poetry_locks/python_lower_bound.toml
new file mode 100644
index 00000000000..f8289d24565
--- /dev/null
+++ b/uv/spec/fixtures/poetry_locks/python_lower_bound.toml
@@ -0,0 +1,149 @@
+# This file is automatically @generated by Poetry 1.6.1 and should not be changed by hand.
+
+[[package]]
+name = "a-dependency"
+version = "0.1.0"
+description = ""
+optional = false
+python-versions = ">=3.9.10,<3.10"
+files = []
+develop = false
+
+[package.source]
+type = "directory"
+url = "a-dependency"
+
+[[package]]
+name = "black"
+version = "22.6.0"
+description = "The uncompromising code formatter."
+optional = false
+python-versions = ">=3.6.2"
+files = [
+ {file = "black-22.6.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:f586c26118bc6e714ec58c09df0157fe2d9ee195c764f630eb0d8e7ccce72e69"},
+ {file = "black-22.6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b270a168d69edb8b7ed32c193ef10fd27844e5c60852039599f9184460ce0807"},
+ {file = "black-22.6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6797f58943fceb1c461fb572edbe828d811e719c24e03375fd25170ada53825e"},
+ {file = "black-22.6.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c85928b9d5f83b23cee7d0efcb310172412fbf7cb9d9ce963bd67fd141781def"},
+ {file = "black-22.6.0-cp310-cp310-win_amd64.whl", hash = "sha256:f6fe02afde060bbeef044af7996f335fbe90b039ccf3f5eb8f16df8b20f77666"},
+ {file = "black-22.6.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:cfaf3895a9634e882bf9d2363fed5af8888802d670f58b279b0bece00e9a872d"},
+ {file = "black-22.6.0-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:94783f636bca89f11eb5d50437e8e17fbc6a929a628d82304c80fa9cd945f256"},
+ {file = "black-22.6.0-cp36-cp36m-win_amd64.whl", hash = "sha256:2ea29072e954a4d55a2ff58971b83365eba5d3d357352a07a7a4df0d95f51c78"},
+ {file = "black-22.6.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:e439798f819d49ba1c0bd9664427a05aab79bfba777a6db94fd4e56fae0cb849"},
+ {file = "black-22.6.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:187d96c5e713f441a5829e77120c269b6514418f4513a390b0499b0987f2ff1c"},
+ {file = "black-22.6.0-cp37-cp37m-win_amd64.whl", hash = "sha256:074458dc2f6e0d3dab7928d4417bb6957bb834434516f21514138437accdbe90"},
+ {file = "black-22.6.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:a218d7e5856f91d20f04e931b6f16d15356db1c846ee55f01bac297a705ca24f"},
+ {file = "black-22.6.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:568ac3c465b1c8b34b61cd7a4e349e93f91abf0f9371eda1cf87194663ab684e"},
+ {file = "black-22.6.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:6c1734ab264b8f7929cef8ae5f900b85d579e6cbfde09d7387da8f04771b51c6"},
+ {file = "black-22.6.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c9a3ac16efe9ec7d7381ddebcc022119794872abce99475345c5a61aa18c45ad"},
+ {file = "black-22.6.0-cp38-cp38-win_amd64.whl", hash = "sha256:b9fd45787ba8aa3f5e0a0a98920c1012c884622c6c920dbe98dbd05bc7c70fbf"},
+ {file = "black-22.6.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7ba9be198ecca5031cd78745780d65a3f75a34b2ff9be5837045dce55db83d1c"},
+ {file = "black-22.6.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a3db5b6409b96d9bd543323b23ef32a1a2b06416d525d27e0f67e74f1446c8f2"},
+ {file = "black-22.6.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:560558527e52ce8afba936fcce93a7411ab40c7d5fe8c2463e279e843c0328ee"},
+ {file = "black-22.6.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b154e6bbde1e79ea3260c4b40c0b7b3109ffcdf7bc4ebf8859169a6af72cd70b"},
+ {file = "black-22.6.0-cp39-cp39-win_amd64.whl", hash = "sha256:4af5bc0e1f96be5ae9bd7aaec219c901a94d6caa2484c21983d043371c733fc4"},
+ {file = "black-22.6.0-py3-none-any.whl", hash = "sha256:ac609cf8ef5e7115ddd07d85d988d074ed00e10fbc3445aee393e70164a2219c"},
+ {file = "black-22.6.0.tar.gz", hash = "sha256:6c6d39e28aed379aec40da1c65434c77d75e65bb59a1e1c283de545fb4e7c6c9"},
+]
+
+[package.dependencies]
+click = ">=8.0.0"
+mypy-extensions = ">=0.4.3"
+pathspec = ">=0.9.0"
+platformdirs = ">=2"
+tomli = {version = ">=1.1.0", markers = "python_full_version < \"3.11.0a7\""}
+typing-extensions = {version = ">=3.10.0.0", markers = "python_version < \"3.10\""}
+
+[package.extras]
+colorama = ["colorama (>=0.4.3)"]
+d = ["aiohttp (>=3.7.4)"]
+jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"]
+uvloop = ["uvloop (>=0.15.2)"]
+
+[[package]]
+name = "click"
+version = "8.1.6"
+description = "Composable command line interface toolkit"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "click-8.1.6-py3-none-any.whl", hash = "sha256:fa244bb30b3b5ee2cae3da8f55c9e5e0c0e86093306301fb418eb9dc40fbded5"},
+ {file = "click-8.1.6.tar.gz", hash = "sha256:48ee849951919527a045bfe3bf7baa8a959c423134e1a5b98c05c20ba75a1cbd"},
+]
+
+[package.dependencies]
+colorama = {version = "*", markers = "platform_system == \"Windows\""}
+
+[[package]]
+name = "colorama"
+version = "0.4.6"
+description = "Cross-platform colored terminal text."
+optional = false
+python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
+files = [
+ {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"},
+ {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
+]
+
+[[package]]
+name = "mypy-extensions"
+version = "1.0.0"
+description = "Type system extensions for programs checked with the mypy type checker."
+optional = false
+python-versions = ">=3.5"
+files = [
+ {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"},
+ {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"},
+]
+
+[[package]]
+name = "pathspec"
+version = "0.11.2"
+description = "Utility library for gitignore style pattern matching of file paths."
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "pathspec-0.11.2-py3-none-any.whl", hash = "sha256:1d6ed233af05e679efb96b1851550ea95bbb64b7c490b0f5aa52996c11e92a20"},
+ {file = "pathspec-0.11.2.tar.gz", hash = "sha256:e0d8d0ac2f12da61956eb2306b69f9469b42f4deb0f3cb6ed47b9cce9996ced3"},
+]
+
+[[package]]
+name = "platformdirs"
+version = "3.10.0"
+description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "platformdirs-3.10.0-py3-none-any.whl", hash = "sha256:d7c24979f292f916dc9cbf8648319032f551ea8c49a4c9bf2fb556a02070ec1d"},
+ {file = "platformdirs-3.10.0.tar.gz", hash = "sha256:b45696dab2d7cc691a3226759c0d3b00c47c8b6e293d96f6436f733303f77f6d"},
+]
+
+[package.extras]
+docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.1)", "sphinx-autodoc-typehints (>=1.24)"]
+test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4)", "pytest-cov (>=4.1)", "pytest-mock (>=3.11.1)"]
+
+[[package]]
+name = "tomli"
+version = "2.0.1"
+description = "A lil' TOML parser"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"},
+ {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"},
+]
+
+[[package]]
+name = "typing-extensions"
+version = "4.7.1"
+description = "Backported and Experimental Type Hints for Python 3.7+"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "typing_extensions-4.7.1-py3-none-any.whl", hash = "sha256:440d5dd3af93b060174bf433bccd69b0babc3b15b1a8dca43789fd7f61514b36"},
+ {file = "typing_extensions-4.7.1.tar.gz", hash = "sha256:b75ddc264f0ba5615db7ba217daeb99701ad295353c45f9e95963337ceeeffb2"},
+]
+
+[metadata]
+lock-version = "2.0"
+python-versions = ">=3.9.10,<3.10"
+content-hash = "193d0b7dd2f5320281d2826ae32ed983f375e40a1f769a3ed68550d9ba700618"
diff --git a/uv/spec/fixtures/poetry_locks/url_dependency.lock b/uv/spec/fixtures/poetry_locks/url_dependency.lock
new file mode 100644
index 00000000000..6b242ed2295
--- /dev/null
+++ b/uv/spec/fixtures/poetry_locks/url_dependency.lock
@@ -0,0 +1,204 @@
+[[package]]
+name = "atomicwrites"
+version = "1.4.0"
+description = "Atomic file writes."
+category = "main"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+
+[[package]]
+name = "attrs"
+version = "21.2.0"
+description = "Classes Without Boilerplate"
+category = "main"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
+
+[package.extras]
+dev = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface", "furo", "sphinx", "sphinx-notfound-page", "pre-commit"]
+docs = ["furo", "sphinx", "zope.interface", "sphinx-notfound-page"]
+tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface"]
+tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins"]
+
+[[package]]
+name = "colorama"
+version = "0.4.4"
+description = "Cross-platform colored terminal text."
+category = "main"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
+
+[[package]]
+name = "importlib-metadata"
+version = "4.5.0"
+description = "Read metadata from Python packages"
+category = "main"
+optional = false
+python-versions = ">=3.6"
+
+[package.dependencies]
+typing-extensions = {version = ">=3.6.4", markers = "python_version < \"3.8\""}
+zipp = ">=0.5"
+
+[package.extras]
+docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)"]
+testing = ["pytest (>=4.6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "packaging", "pep517", "pyfakefs", "flufl.flake8", "pytest-black (>=0.3.7)", "pytest-mypy", "importlib-resources (>=1.3)"]
+
+[[package]]
+name = "iniconfig"
+version = "1.1.1"
+description = "iniconfig: brain-dead simple config-ini parsing"
+category = "main"
+optional = false
+python-versions = "*"
+
+[[package]]
+name = "packaging"
+version = "20.9"
+description = "Core utilities for Python packages"
+category = "main"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+
+[package.dependencies]
+pyparsing = ">=2.0.2"
+
+[[package]]
+name = "pluggy"
+version = "0.13.1"
+description = "plugin and hook calling mechanisms for python"
+category = "main"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+
+[package.dependencies]
+importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""}
+
+[package.extras]
+dev = ["pre-commit", "tox"]
+
+[[package]]
+name = "py"
+version = "1.10.0"
+description = "library with cross-python path, ini-parsing, io, code, log facilities"
+category = "main"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+
+[[package]]
+name = "pyparsing"
+version = "2.4.7"
+description = "Python parsing module"
+category = "main"
+optional = false
+python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
+
+[[package]]
+name = "pytest"
+version = "6.2.4"
+description = "pytest: simple powerful testing with Python"
+category = "main"
+optional = false
+python-versions = ">=3.6"
+
+[package.dependencies]
+atomicwrites = {version = ">=1.0", markers = "sys_platform == \"win32\""}
+attrs = ">=19.2.0"
+colorama = {version = "*", markers = "sys_platform == \"win32\""}
+importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""}
+iniconfig = "*"
+packaging = "*"
+pluggy = ">=0.12,<1.0.0a1"
+py = ">=1.8.2"
+toml = "*"
+
+[package.extras]
+testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "requests", "xmlschema"]
+
+[[package]]
+name = "toml"
+version = "0.10.2"
+description = "Python Library for Tom's Obvious, Minimal Language"
+category = "main"
+optional = false
+python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
+
+[package.source]
+type = "url"
+url = "https://github.com/uiri/toml/archive/refs/tags/0.10.2.tar.gz"
+[[package]]
+name = "typing-extensions"
+version = "3.10.0.0"
+description = "Backported and Experimental Type Hints for Python 3.5+"
+category = "main"
+optional = false
+python-versions = "*"
+
+[[package]]
+name = "zipp"
+version = "3.4.1"
+description = "Backport of pathlib-compatible object wrapper for zip files"
+category = "main"
+optional = false
+python-versions = ">=3.6"
+
+[package.extras]
+docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)"]
+testing = ["pytest (>=4.6)", "pytest-checkdocs (>=1.2.3)", "pytest-flake8", "pytest-cov", "pytest-enabler", "jaraco.itertools", "func-timeout", "pytest-black (>=0.3.7)", "pytest-mypy"]
+
+[metadata]
+lock-version = "1.1"
+python-versions = "^3.7"
+content-hash = "b35acc0830421bdc03a2d1d9f3669c764225bf47897ea5cd9671b6f797301211"
+
+[metadata.files]
+atomicwrites = [
+ {file = "atomicwrites-1.4.0-py2.py3-none-any.whl", hash = "sha256:6d1784dea7c0c8d4a5172b6c620f40b6e4cbfdf96d783691f2e1302a7b88e197"},
+ {file = "atomicwrites-1.4.0.tar.gz", hash = "sha256:ae70396ad1a434f9c7046fd2dd196fc04b12f9e91ffb859164193be8b6168a7a"},
+]
+attrs = [
+ {file = "attrs-21.2.0-py2.py3-none-any.whl", hash = "sha256:149e90d6d8ac20db7a955ad60cf0e6881a3f20d37096140088356da6c716b0b1"},
+ {file = "attrs-21.2.0.tar.gz", hash = "sha256:ef6aaac3ca6cd92904cdd0d83f629a15f18053ec84e6432106f7a4d04ae4f5fb"},
+]
+colorama = [
+ {file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"},
+ {file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"},
+]
+importlib-metadata = [
+ {file = "importlib_metadata-4.5.0-py3-none-any.whl", hash = "sha256:833b26fb89d5de469b24a390e9df088d4e52e4ba33b01dc5e0e4f41b81a16c00"},
+ {file = "importlib_metadata-4.5.0.tar.gz", hash = "sha256:b142cc1dd1342f31ff04bb7d022492b09920cb64fed867cd3ea6f80fe3ebd139"},
+]
+iniconfig = [
+ {file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"},
+ {file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"},
+]
+packaging = [
+ {file = "packaging-20.9-py2.py3-none-any.whl", hash = "sha256:67714da7f7bc052e064859c05c595155bd1ee9f69f76557e21f051443c20947a"},
+ {file = "packaging-20.9.tar.gz", hash = "sha256:5b327ac1320dc863dca72f4514ecc086f31186744b84a230374cc1fd776feae5"},
+]
+pluggy = [
+ {file = "pluggy-0.13.1-py2.py3-none-any.whl", hash = "sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d"},
+ {file = "pluggy-0.13.1.tar.gz", hash = "sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0"},
+]
+py = [
+ {file = "py-1.10.0-py2.py3-none-any.whl", hash = "sha256:3b80836aa6d1feeaa108e046da6423ab8f6ceda6468545ae8d02d9d58d18818a"},
+ {file = "py-1.10.0.tar.gz", hash = "sha256:21b81bda15b66ef5e1a777a21c4dcd9c20ad3efd0b3f817e7a809035269e1bd3"},
+]
+pyparsing = [
+ {file = "pyparsing-2.4.7-py2.py3-none-any.whl", hash = "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b"},
+ {file = "pyparsing-2.4.7.tar.gz", hash = "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1"},
+]
+pytest = [
+ {file = "pytest-6.2.4-py3-none-any.whl", hash = "sha256:91ef2131a9bd6be8f76f1f08eac5c5317221d6ad1e143ae03894b862e8976890"},
+ {file = "pytest-6.2.4.tar.gz", hash = "sha256:50bcad0a0b9c5a72c8e4e7c9855a3ad496ca6a881a3641b4260605450772c54b"},
+]
+toml = []
+typing-extensions = [
+ {file = "typing_extensions-3.10.0.0-py2-none-any.whl", hash = "sha256:0ac0f89795dd19de6b97debb0c6af1c70987fd80a2d62d1958f7e56fcc31b497"},
+ {file = "typing_extensions-3.10.0.0-py3-none-any.whl", hash = "sha256:779383f6086d90c99ae41cf0ff39aac8a7937a9283ce0a414e5dd782f4c94a84"},
+ {file = "typing_extensions-3.10.0.0.tar.gz", hash = "sha256:50b6f157849174217d0656f99dc82fe932884fb250826c18350e159ec6cdf342"},
+]
+zipp = [
+ {file = "zipp-3.4.1-py3-none-any.whl", hash = "sha256:51cb66cc54621609dd593d1787f286ee42a5c0adbb4b29abea5a63edc3e03098"},
+ {file = "zipp-3.4.1.tar.gz", hash = "sha256:3607921face881ba3e026887d8150cca609d517579abe052ac81fc5aeffdbd76"},
+]
diff --git a/uv/spec/fixtures/poetry_locks/version_not_specified.lock b/uv/spec/fixtures/poetry_locks/version_not_specified.lock
new file mode 100644
index 00000000000..6301e2cf30c
--- /dev/null
+++ b/uv/spec/fixtures/poetry_locks/version_not_specified.lock
@@ -0,0 +1,150 @@
+[[package]]
+category = "main"
+description = "Classes Without Boilerplate"
+name = "attrs"
+optional = false
+platform = "*"
+python-versions = "*"
+version = "18.1.0"
+
+[[package]]
+category = "main"
+description = "Python package for providing Mozilla's CA Bundle."
+name = "certifi"
+optional = false
+platform = "*"
+python-versions = "*"
+version = "2018.4.16"
+
+[[package]]
+category = "main"
+description = "Universal encoding detector for Python 2 and 3"
+name = "chardet"
+optional = false
+platform = "*"
+python-versions = "*"
+version = "3.0.4"
+
+[[package]]
+category = "main"
+description = "Cross-platform colored terminal text."
+name = "colorama"
+optional = false
+platform = "UNKNOWN"
+python-versions = "*"
+version = "0.3.9"
+
+[package.requirements]
+platform = "win32"
+
+[[package]]
+category = "main"
+description = "Internationalized Domain Names in Applications (IDNA)"
+name = "idna"
+optional = false
+platform = "UNKNOWN"
+python-versions = "*"
+version = "2.5"
+
+[[package]]
+category = "main"
+description = "More routines for operating on iterables, beyond itertools"
+name = "more-itertools"
+optional = false
+platform = "*"
+python-versions = "*"
+version = "4.3.0"
+
+[package.dependencies]
+six = ">=1.0.0,<2.0.0"
+
+[[package]]
+category = "main"
+description = "plugin and hook calling mechanisms for python"
+name = "pluggy"
+optional = false
+platform = "unix"
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+version = "0.6.0"
+
+[[package]]
+category = "main"
+description = "library with cross-python path, ini-parsing, io, code, log facilities"
+name = "py"
+optional = false
+platform = "unix"
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+version = "1.5.4"
+
+[[package]]
+category = "main"
+description = "pytest: simple powerful testing with Python"
+name = "pytest"
+optional = false
+platform = "unix"
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+version = "3.5.0"
+
+[package.dependencies]
+attrs = ">=17.4.0"
+more-itertools = ">=4.0.0"
+pluggy = ">=0.5,<0.7"
+py = ">=1.5.0"
+setuptools = "*"
+six = ">=1.10.0"
+
+[package.dependencies.colorama]
+platform = "win32"
+version = "*"
+
+[[package]]
+category = "main"
+description = "Python HTTP for Humans."
+name = "requests"
+optional = false
+platform = "*"
+python-versions = "*"
+version = "2.18.0"
+
+[package.dependencies]
+certifi = ">=2017.4.17"
+chardet = ">=3.0.2,<3.1.0"
+idna = ">=2.5,<2.6"
+urllib3 = ">=1.21.1,<1.22"
+
+[[package]]
+category = "main"
+description = "Python 2 and 3 compatibility utilities"
+name = "six"
+optional = false
+platform = "*"
+python-versions = "*"
+version = "1.11.0"
+
+[[package]]
+category = "main"
+description = "HTTP library with thread-safe connection pooling, file post, and more."
+name = "urllib3"
+optional = false
+platform = "*"
+python-versions = "*"
+version = "1.21.1"
+
+[metadata]
+content-hash = "82505f37a0da79b1e0f8d5c715d5435ef9318adf4df0e7372bded484f7cdb27a"
+platform = "*"
+python-versions = "^3.7"
+
+[metadata.hashes]
+attrs = ["4b90b09eeeb9b88c35bc642cbac057e45a5fd85367b985bd2809c62b7b939265", "e0d0eb91441a3b53dab4d9b743eafc1ac44476296a2053b6ca3af0b139faf87b"]
+certifi = ["13e698f54293db9f89122b0581843a782ad0934a4fe0172d2a980ba77fc61bb7", "9fa520c1bacfb634fa7af20a76bcbd3d5fb390481724c597da32c719a7dca4b0"]
+chardet = ["84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae", "fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"]
+colorama = ["463f8483208e921368c9f306094eb6f725c6ca42b0f97e313cb5d5512459feda", "48eb22f4f8461b1df5734a074b57042430fb06e1d61bd1e11b078c0fe6d7a1f1"]
+idna = ["3cb5ce08046c4e3a560fc02f138d0ac63e00f8ce5901a56b32ec8b7994082aab", "cc19709fd6d0cbfed39ea875d29ba6d4e22c0cebc510a76d6302a28385e8bb70"]
+more-itertools = ["c187a73da93e7a8acc0001572aebc7e3c69daf7bf6881a2cea10650bd4420092", "c476b5d3a34e12d40130bc2f935028b5f636df8f372dc2c1c01dc19681b2039e", "fcbfeaea0be121980e15bc97b3817b5202ca73d0eae185b4550cbfce2a3ebb3d"]
+pluggy = ["7f8ae7f5bdf75671a718d2daf0a64b7885f74510bcd98b1a0bb420eb9a9d0cff", "d345c8fe681115900d6da8d048ba67c25df42973bda370783cd58826442dcd7c", "e160a7fcf25762bb60efc7e171d4497ff1d8d2d75a3d0df7a21b76821ecbf5c5"]
+py = ["3fd59af7435864e1a243790d322d763925431213b6b8529c6ca71081ace3bbf7", "e31fb2767eb657cbde86c454f02e99cb846d3cd9d61b318525140214fdc0e98e"]
+pytest = ["6266f87ab64692112e5477eba395cfedda53b1933ccd29478e671e73b420c19c", "fae491d1874f199537fd5872b5e1f0e74a009b979df9d53d1553fd03da1703e1"]
+requests = ["5e88d64aa56ac0fda54e77fb9762ebc65879e171b746d5479a33c4082519d6c6", "cd0189f962787284bff715fddaad478eb4d9c15aa167bd64e52ea0f661e7ea5c"]
+six = ["70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9", "832dc0e10feb1aa2c68dcc57dbb658f1c7e65b9b61af69048abc87a2db00a0eb"]
+urllib3 = ["8ed6d5c1ff9d6ba84677310060d6a3a78ca3072ce0684cb3c645023009c114b1", "b14486978518ca0901a76ba973d7821047409d7f726f22156b24e83fd71382a5"]
diff --git a/uv/spec/fixtures/poetry_locks/yanked_version.lock b/uv/spec/fixtures/poetry_locks/yanked_version.lock
new file mode 100644
index 00000000000..eea266aed56
--- /dev/null
+++ b/uv/spec/fixtures/poetry_locks/yanked_version.lock
@@ -0,0 +1,97 @@
+[[package]]
+category = "main"
+description = "Python package for providing Mozilla's CA Bundle."
+name = "certifi"
+optional = false
+python-versions = "*"
+version = "2019.3.9"
+
+[[package]]
+category = "main"
+description = "Universal encoding detector for Python 2 and 3"
+name = "chardet"
+optional = false
+python-versions = "*"
+version = "3.0.4"
+
+[[package]]
+category = "dev"
+description = "croniter provides iteration for datetime object with cron like format"
+name = "croniter"
+optional = false
+python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+version = "0.3.26"
+
+[package.dependencies]
+python-dateutil = "*"
+
+[[package]]
+category = "main"
+description = "Internationalized Domain Names in Applications (IDNA)"
+name = "idna"
+optional = false
+python-versions = "*"
+version = "2.5"
+
+[[package]]
+category = "dev"
+description = "Extensions to the standard Python datetime module"
+name = "python-dateutil"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*"
+version = "2.8.0"
+
+[package.dependencies]
+six = ">=1.5"
+
+[[package]]
+category = "main"
+description = "Python HTTP for Humans."
+name = "requests"
+optional = false
+python-versions = "*"
+version = "2.18.0"
+
+[package.dependencies]
+certifi = ">=2017.4.17"
+chardet = ">=3.0.2,<3.1.0"
+idna = ">=2.5,<2.6"
+urllib3 = ">=1.21.1,<1.22"
+
+[package.extras]
+security = ["cryptography (>=1.3.4)", "idna (>=2.0.0)", "pyOpenSSL (>=0.14)"]
+socks = ["PySocks (>=1.5.6,<1.5.7 || >1.5.7)", "win-inet-pton"]
+
+[[package]]
+category = "dev"
+description = "Python 2 and 3 compatibility utilities"
+name = "six"
+optional = false
+python-versions = ">=2.6, !=3.0.*, !=3.1.*"
+version = "1.12.0"
+
+[[package]]
+category = "main"
+description = "HTTP library with thread-safe connection pooling, file post, and more."
+name = "urllib3"
+optional = false
+python-versions = "*"
+version = "1.21.1"
+
+[package.extras]
+secure = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "certifi", "ipaddress"]
+socks = ["PySocks (>=1.5.6,<1.5.7 || >1.5.7,<2.0)"]
+
+[metadata]
+content-hash = "59c2b37279d6cbfb094ec0e99526f4559bd904cab1d48906d03ab6b35d63b7d9"
+python-versions = "*"
+
+[metadata.hashes]
+certifi = ["59b7658e26ca9c7339e00f8f4636cdfe59d34fa37b9b04f6f9e9926b3cece1a5", "b26104d6835d1f5e49452a26eb2ff87fe7090b89dfcaee5ea2212697e1e1d7ae"]
+chardet = ["84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae", "fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"]
+croniter = ["8dc579890b0bfd10cfc60a2c314de82adf06004bd90d0d7d5b384e19e93a7720", "b9f2aa83a3db1dcea75e222d533793c22d737b0d5eb8ed7ccc5bfa6e067d10ed"]
+idna = ["3cb5ce08046c4e3a560fc02f138d0ac63e00f8ce5901a56b32ec8b7994082aab", "cc19709fd6d0cbfed39ea875d29ba6d4e22c0cebc510a76d6302a28385e8bb70"]
+python-dateutil = ["7e6584c74aeed623791615e26efd690f29817a27c73085b78e4bad02493df2fb", "c89805f6f4d64db21ed966fda138f8a5ed7a4fdbc1a8ee329ce1b74e3c74da9e"]
+requests = ["5e88d64aa56ac0fda54e77fb9762ebc65879e171b746d5479a33c4082519d6c6", "cd0189f962787284bff715fddaad478eb4d9c15aa167bd64e52ea0f661e7ea5c"]
+six = ["3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c", "d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73"]
+urllib3 = ["8ed6d5c1ff9d6ba84677310060d6a3a78ca3072ce0684cb3c645023009c114b1", "b14486978518ca0901a76ba973d7821047409d7f726f22156b24e83fd71382a5"]
diff --git a/uv/spec/fixtures/projects/pipenv/editable-package/Pipfile b/uv/spec/fixtures/projects/pipenv/editable-package/Pipfile
new file mode 100644
index 00000000000..5535472b8a4
--- /dev/null
+++ b/uv/spec/fixtures/projects/pipenv/editable-package/Pipfile
@@ -0,0 +1,16 @@
+[dev-packages]
+cryptography = "==40.0.1"
+[dev-packages.ballcone]
+editable = true
+extras = ["dev"]
+path = "."
+[packages.ballcone]
+editable = true
+path = "."
+[requires]
+[scripts]
+test = "python3 -m unittest discover"
+[[source]]
+name = "pypi"
+url = "https://pypi.python.org/simple"
+verify_ssl = true
diff --git a/uv/spec/fixtures/projects/pipenv/editable-package/Pipfile.lock b/uv/spec/fixtures/projects/pipenv/editable-package/Pipfile.lock
new file mode 100644
index 00000000000..1054c9a7687
--- /dev/null
+++ b/uv/spec/fixtures/projects/pipenv/editable-package/Pipfile.lock
@@ -0,0 +1,119 @@
+{
+ "_meta": {
+ "hash": {
+ "sha256": "786a4e40a998579a379e7ef7976fd68bf8862c4a03cda000933ffbf515517046"
+ },
+ "pipfile-spec": 6,
+ "requires": {},
+ "sources": [
+ {
+ "name": "pypi",
+ "url": "https://pypi.python.org/simple",
+ "verify_ssl": true
+ }
+ ]
+ },
+ "default": {
+ "ballcone": {
+ "editable": true,
+ "path": "."
+ }
+ },
+ "develop": {
+ "ballcone": {
+ "editable": true,
+ "path": "."
+ },
+ "cffi": {
+ "hashes": [
+ "sha256:0c9ef6ff37e974b73c25eecc13952c55bceed9112be2d9d938ded8e856138bcc",
+ "sha256:131fd094d1065b19540c3d72594260f118b231090295d8c34e19a7bbcf2e860a",
+ "sha256:1b8ebc27c014c59692bb2664c7d13ce7a6e9a629be20e54e7271fa696ff2b417",
+ "sha256:2c56b361916f390cd758a57f2e16233eb4f64bcbeee88a4881ea90fca14dc6ab",
+ "sha256:2d92b25dbf6cae33f65005baf472d2c245c050b1ce709cc4588cdcdd5495b520",
+ "sha256:31d13b0f99e0836b7ff893d37af07366ebc90b678b6664c955b54561fc36ef36",
+ "sha256:32c68ef735dbe5857c810328cb2481e24722a59a2003018885514d4c09af9743",
+ "sha256:3686dffb02459559c74dd3d81748269ffb0eb027c39a6fc99502de37d501faa8",
+ "sha256:582215a0e9adbe0e379761260553ba11c58943e4bbe9c36430c4ca6ac74b15ed",
+ "sha256:5b50bf3f55561dac5438f8e70bfcdfd74543fd60df5fa5f62d94e5867deca684",
+ "sha256:5bf44d66cdf9e893637896c7faa22298baebcd18d1ddb6d2626a6e39793a1d56",
+ "sha256:6602bc8dc6f3a9e02b6c22c4fc1e47aa50f8f8e6d3f78a5e16ac33ef5fefa324",
+ "sha256:673739cb539f8cdaa07d92d02efa93c9ccf87e345b9a0b556e3ecc666718468d",
+ "sha256:68678abf380b42ce21a5f2abde8efee05c114c2fdb2e9eef2efdb0257fba1235",
+ "sha256:68e7c44931cc171c54ccb702482e9fc723192e88d25a0e133edd7aff8fcd1f6e",
+ "sha256:6b3d6606d369fc1da4fd8c357d026317fbb9c9b75d36dc16e90e84c26854b088",
+ "sha256:748dcd1e3d3d7cd5443ef03ce8685043294ad6bd7c02a38d1bd367cfd968e000",
+ "sha256:7651c50c8c5ef7bdb41108b7b8c5a83013bfaa8a935590c5d74627c047a583c7",
+ "sha256:7b78010e7b97fef4bee1e896df8a4bbb6712b7f05b7ef630f9d1da00f6444d2e",
+ "sha256:7e61e3e4fa664a8588aa25c883eab612a188c725755afff6289454d6362b9673",
+ "sha256:80876338e19c951fdfed6198e70bc88f1c9758b94578d5a7c4c91a87af3cf31c",
+ "sha256:8895613bcc094d4a1b2dbe179d88d7fb4a15cee43c052e8885783fac397d91fe",
+ "sha256:88e2b3c14bdb32e440be531ade29d3c50a1a59cd4e51b1dd8b0865c54ea5d2e2",
+ "sha256:8f8e709127c6c77446a8c0a8c8bf3c8ee706a06cd44b1e827c3e6a2ee6b8c098",
+ "sha256:9cb4a35b3642fc5c005a6755a5d17c6c8b6bcb6981baf81cea8bfbc8903e8ba8",
+ "sha256:9f90389693731ff1f659e55c7d1640e2ec43ff725cc61b04b2f9c6d8d017df6a",
+ "sha256:a09582f178759ee8128d9270cd1344154fd473bb77d94ce0aeb2a93ebf0feaf0",
+ "sha256:a6a14b17d7e17fa0d207ac08642c8820f84f25ce17a442fd15e27ea18d67c59b",
+ "sha256:a72e8961a86d19bdb45851d8f1f08b041ea37d2bd8d4fd19903bc3083d80c896",
+ "sha256:abd808f9c129ba2beda4cfc53bde801e5bcf9d6e0f22f095e45327c038bfe68e",
+ "sha256:ac0f5edd2360eea2f1daa9e26a41db02dd4b0451b48f7c318e217ee092a213e9",
+ "sha256:b29ebffcf550f9da55bec9e02ad430c992a87e5f512cd63388abb76f1036d8d2",
+ "sha256:b2ca4e77f9f47c55c194982e10f058db063937845bb2b7a86c84a6cfe0aefa8b",
+ "sha256:b7be2d771cdba2942e13215c4e340bfd76398e9227ad10402a8767ab1865d2e6",
+ "sha256:b84834d0cf97e7d27dd5b7f3aca7b6e9263c56308ab9dc8aae9784abb774d404",
+ "sha256:b86851a328eedc692acf81fb05444bdf1891747c25af7529e39ddafaf68a4f3f",
+ "sha256:bcb3ef43e58665bbda2fb198698fcae6776483e0c4a631aa5647806c25e02cc0",
+ "sha256:c0f31130ebc2d37cdd8e44605fb5fa7ad59049298b3f745c74fa74c62fbfcfc4",
+ "sha256:c6a164aa47843fb1b01e941d385aab7215563bb8816d80ff3a363a9f8448a8dc",
+ "sha256:d8a9d3ebe49f084ad71f9269834ceccbf398253c9fac910c4fd7053ff1386936",
+ "sha256:db8e577c19c0fda0beb7e0d4e09e0ba74b1e4c092e0e40bfa12fe05b6f6d75ba",
+ "sha256:dc9b18bf40cc75f66f40a7379f6a9513244fe33c0e8aa72e2d56b0196a7ef872",
+ "sha256:e09f3ff613345df5e8c3667da1d918f9149bd623cd9070c983c013792a9a62eb",
+ "sha256:e4108df7fe9b707191e55f33efbcb2d81928e10cea45527879a4749cbe472614",
+ "sha256:e6024675e67af929088fda399b2094574609396b1decb609c55fa58b028a32a1",
+ "sha256:e70f54f1796669ef691ca07d046cd81a29cb4deb1e5f942003f401c0c4a2695d",
+ "sha256:e715596e683d2ce000574bae5d07bd522c781a822866c20495e52520564f0969",
+ "sha256:e760191dd42581e023a68b758769e2da259b5d52e3103c6060ddc02c9edb8d7b",
+ "sha256:ed86a35631f7bfbb28e108dd96773b9d5a6ce4811cf6ea468bb6a359b256b1e4",
+ "sha256:ee07e47c12890ef248766a6e55bd38ebfb2bb8edd4142d56db91b21ea68b7627",
+ "sha256:fa3a0128b152627161ce47201262d3140edb5a5c3da88d73a1b790a959126956",
+ "sha256:fcc8eb6d5902bb1cf6dc4f187ee3ea80a1eba0a89aba40a5cb20a5087d961357"
+ ],
+ "markers": "python_version >= '3.8'",
+ "version": "==1.16.0"
+ },
+ "cryptography": {
+ "hashes": [
+ "sha256:0a4e3406cfed6b1f6d6e87ed243363652b2586b2d917b0609ca4f97072994405",
+ "sha256:1e0af458515d5e4028aad75f3bb3fe7a31e46ad920648cd59b64d3da842e4356",
+ "sha256:2803f2f8b1e95f614419926c7e6f55d828afc614ca5ed61543877ae668cc3472",
+ "sha256:28d63d75bf7ae4045b10de5413fb1d6338616e79015999ad9cf6fc538f772d41",
+ "sha256:32057d3d0ab7d4453778367ca43e99ddb711770477c4f072a51b3ca69602780a",
+ "sha256:3a4805a4ca729d65570a1b7cac84eac1e431085d40387b7d3bbaa47e39890b88",
+ "sha256:63dac2d25c47f12a7b8aa60e528bfb3c51c5a6c5a9f7c86987909c6c79765554",
+ "sha256:650883cc064297ef3676b1db1b7b1df6081794c4ada96fa457253c4cc40f97db",
+ "sha256:6f2bbd72f717ce33100e6467572abaedc61f1acb87b8d546001328d7f466b778",
+ "sha256:7c872413353c70e0263a9368c4993710070e70ab3e5318d85510cc91cce77e7c",
+ "sha256:918cb89086c7d98b1b86b9fdb70c712e5a9325ba6f7d7cfb509e784e0cfc6917",
+ "sha256:9618a87212cb5200500e304e43691111570e1f10ec3f35569fdfcd17e28fd797",
+ "sha256:a805a7bce4a77d51696410005b3e85ae2839bad9aa38894afc0aa99d8e0c3160",
+ "sha256:cc3a621076d824d75ab1e1e530e66e7e8564e357dd723f2533225d40fe35c60c",
+ "sha256:cd033d74067d8928ef00a6b1327c8ea0452523967ca4463666eeba65ca350d4c",
+ "sha256:cf91e428c51ef692b82ce786583e214f58392399cf65c341bc7301d096fa3ba2",
+ "sha256:d36bbeb99704aabefdca5aee4eba04455d7a27ceabd16f3b3ba9bdcc31da86c4",
+ "sha256:d8aa3609d337ad85e4eb9bb0f8bcf6e4409bfb86e706efa9a027912169e89122",
+ "sha256:f5d7b79fa56bc29580faafc2ff736ce05ba31feaa9d4735048b0de7d9ceb2b94"
+ ],
+ "index": "pypi",
+ "markers": "python_version >= '3.6'",
+ "version": "==40.0.1"
+ },
+ "pycparser": {
+ "hashes": [
+ "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9",
+ "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"
+ ],
+ "version": "==2.21"
+ }
+ }
+}
diff --git a/uv/spec/fixtures/projects/pipenv/editable-package/ballcone/__init__.py b/uv/spec/fixtures/projects/pipenv/editable-package/ballcone/__init__.py
new file mode 100644
index 00000000000..d38b46d568e
--- /dev/null
+++ b/uv/spec/fixtures/projects/pipenv/editable-package/ballcone/__init__.py
@@ -0,0 +1,3 @@
+__version__ = '0'
+__author__ = 'Dmitry Ustalov'
+__license__ = 'MIT'
diff --git a/uv/spec/fixtures/projects/pipenv/editable-package/pyproject.toml b/uv/spec/fixtures/projects/pipenv/editable-package/pyproject.toml
new file mode 100644
index 00000000000..355149a8ad2
--- /dev/null
+++ b/uv/spec/fixtures/projects/pipenv/editable-package/pyproject.toml
@@ -0,0 +1,52 @@
+[build-system]
+requires = ["setuptools"]
+build-backend = "setuptools.build_meta"
+
+[project]
+name = "ballcone"
+authors = [{name = "Dmitry Ustalov"}]
+classifiers = [
+ "Development Status :: 3 - Alpha",
+ "Intended Audience :: Developers",
+ "Intended Audience :: Information Technology",
+ "License :: OSI Approved :: MIT License",
+ "Operating System :: OS Independent",
+ "Programming Language :: Python :: 3",
+ "Topic :: Database",
+ "Topic :: Internet :: Log Analysis",
+ "Topic :: Internet :: WWW/HTTP",
+ "Typing :: Typed",
+]
+license = {text = "MIT"}
+description = "Ballcone is a fast and lightweight server-side Web analytics solution."
+keywords = ["Web analytics", "log analysis", "columnar storage", "syslog", "nginx"]
+urls = {Homepage = "https://github.com/dustalov/ballcone"}
+requires-python = "~=3.9"
+dependencies = []
+dynamic = ["version"]
+
+[project.readme]
+file = "README.md"
+content-type = "text/markdown"
+
+[project.scripts]
+ballcone = "ballcone.__main__:main"
+
+[tool.setuptools]
+zip-safe = true
+
+[tool.setuptools.packages.find]
+include = ["ballcone*"]
+
+[tool.setuptools.package-data]
+"*" = ["*.html", "*.js"]
+
+[tool.setuptools.dynamic]
+version = {attr = "ballcone.__version__"}
+
+[tool.mypy]
+ignore_missing_imports = true
+allow_untyped_calls = true
+allow_untyped_decorators = true
+warn_unused_ignores = false
+strict = true
diff --git a/uv/spec/fixtures/projects/pipenv/missing-system-library-old-python/Pipfile b/uv/spec/fixtures/projects/pipenv/missing-system-library-old-python/Pipfile
new file mode 100644
index 00000000000..f0152986f5c
--- /dev/null
+++ b/uv/spec/fixtures/projects/pipenv/missing-system-library-old-python/Pipfile
@@ -0,0 +1,11 @@
+[[source]]
+url = "https://pypi.org/simple"
+verify_ssl = true
+name = "pypi"
+
+[requires]
+python_version = "3.11"
+
+[packages]
+rtree = "==0.9.3"
+requests = "==2.18.0"
diff --git a/uv/spec/fixtures/projects/pipenv/missing-system-library/Pipfile b/uv/spec/fixtures/projects/pipenv/missing-system-library/Pipfile
new file mode 100644
index 00000000000..8fb31f552ad
--- /dev/null
+++ b/uv/spec/fixtures/projects/pipenv/missing-system-library/Pipfile
@@ -0,0 +1,8 @@
+[[source]]
+url = "https://pypi.org/simple"
+verify_ssl = true
+name = "pypi"
+
+[packages]
+rtree = "==0.9.3"
+requests = "==2.18.0"
diff --git a/uv/spec/fixtures/projects/poetry/multiple_requirements/poetry.lock b/uv/spec/fixtures/projects/poetry/multiple_requirements/poetry.lock
new file mode 100644
index 00000000000..1f942718bb1
--- /dev/null
+++ b/uv/spec/fixtures/projects/poetry/multiple_requirements/poetry.lock
@@ -0,0 +1,154 @@
+[[package]]
+name = "numpy"
+version = "1.19.5"
+description = "NumPy is the fundamental package for array computing with Python."
+category = "main"
+optional = false
+python-versions = ">=3.6"
+
+[[package]]
+name = "numpy"
+version = "1.21.1"
+description = "NumPy is the fundamental package for array computing with Python."
+category = "main"
+optional = false
+python-versions = ">=3.7"
+
+[[package]]
+name = "scipy"
+version = "1.5.4"
+description = "SciPy: Scientific Library for Python"
+category = "main"
+optional = false
+python-versions = ">=3.6"
+
+[package.dependencies]
+numpy = ">=1.14.5"
+
+[[package]]
+name = "scipy"
+version = "1.6.1"
+description = "SciPy: Scientific Library for Python"
+category = "main"
+optional = false
+python-versions = ">=3.7"
+
+[package.dependencies]
+numpy = ">=1.16.5"
+
+[metadata]
+lock-version = "1.1"
+python-versions = "*"
+content-hash = "f7f91415d672aa5f9b74f90bf3817fad39116404d3bc8107646bd50a19567624"
+
+[metadata.files]
+numpy = [
+ {file = "numpy-1.19.5-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:cc6bd4fd593cb261332568485e20a0712883cf631f6f5e8e86a52caa8b2b50ff"},
+ {file = "numpy-1.19.5-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:aeb9ed923be74e659984e321f609b9ba54a48354bfd168d21a2b072ed1e833ea"},
+ {file = "numpy-1.19.5-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:8b5e972b43c8fc27d56550b4120fe6257fdc15f9301914380b27f74856299fea"},
+ {file = "numpy-1.19.5-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:43d4c81d5ffdff6bae58d66a3cd7f54a7acd9a0e7b18d97abb255defc09e3140"},
+ {file = "numpy-1.19.5-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:a4646724fba402aa7504cd48b4b50e783296b5e10a524c7a6da62e4a8ac9698d"},
+ {file = "numpy-1.19.5-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:2e55195bc1c6b705bfd8ad6f288b38b11b1af32f3c8289d6c50d47f950c12e76"},
+ {file = "numpy-1.19.5-cp36-cp36m-win32.whl", hash = "sha256:39b70c19ec771805081578cc936bbe95336798b7edf4732ed102e7a43ec5c07a"},
+ {file = "numpy-1.19.5-cp36-cp36m-win_amd64.whl", hash = "sha256:dbd18bcf4889b720ba13a27ec2f2aac1981bd41203b3a3b27ba7a33f88ae4827"},
+ {file = "numpy-1.19.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:603aa0706be710eea8884af807b1b3bc9fb2e49b9f4da439e76000f3b3c6ff0f"},
+ {file = "numpy-1.19.5-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:cae865b1cae1ec2663d8ea56ef6ff185bad091a5e33ebbadd98de2cfa3fa668f"},
+ {file = "numpy-1.19.5-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:36674959eed6957e61f11c912f71e78857a8d0604171dfd9ce9ad5cbf41c511c"},
+ {file = "numpy-1.19.5-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:06fab248a088e439402141ea04f0fffb203723148f6ee791e9c75b3e9e82f080"},
+ {file = "numpy-1.19.5-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:6149a185cece5ee78d1d196938b2a8f9d09f5a5ebfbba66969302a778d5ddd1d"},
+ {file = "numpy-1.19.5-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:50a4a0ad0111cc1b71fa32dedd05fa239f7fb5a43a40663269bb5dc7877cfd28"},
+ {file = "numpy-1.19.5-cp37-cp37m-win32.whl", hash = "sha256:d051ec1c64b85ecc69531e1137bb9751c6830772ee5c1c426dbcfe98ef5788d7"},
+ {file = "numpy-1.19.5-cp37-cp37m-win_amd64.whl", hash = "sha256:a12ff4c8ddfee61f90a1633a4c4afd3f7bcb32b11c52026c92a12e1325922d0d"},
+ {file = "numpy-1.19.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:cf2402002d3d9f91c8b01e66fbb436a4ed01c6498fffed0e4c7566da1d40ee1e"},
+ {file = "numpy-1.19.5-cp38-cp38-manylinux1_i686.whl", hash = "sha256:1ded4fce9cfaaf24e7a0ab51b7a87be9038ea1ace7f34b841fe3b6894c721d1c"},
+ {file = "numpy-1.19.5-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:012426a41bc9ab63bb158635aecccc7610e3eff5d31d1eb43bc099debc979d94"},
+ {file = "numpy-1.19.5-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:759e4095edc3c1b3ac031f34d9459fa781777a93ccc633a472a5468587a190ff"},
+ {file = "numpy-1.19.5-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:a9d17f2be3b427fbb2bce61e596cf555d6f8a56c222bd2ca148baeeb5e5c783c"},
+ {file = "numpy-1.19.5-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:99abf4f353c3d1a0c7a5f27699482c987cf663b1eac20db59b8c7b061eabd7fc"},
+ {file = "numpy-1.19.5-cp38-cp38-win32.whl", hash = "sha256:384ec0463d1c2671170901994aeb6dce126de0a95ccc3976c43b0038a37329c2"},
+ {file = "numpy-1.19.5-cp38-cp38-win_amd64.whl", hash = "sha256:811daee36a58dc79cf3d8bdd4a490e4277d0e4b7d103a001a4e73ddb48e7e6aa"},
+ {file = "numpy-1.19.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c843b3f50d1ab7361ca4f0b3639bf691569493a56808a0b0c54a051d260b7dbd"},
+ {file = "numpy-1.19.5-cp39-cp39-manylinux1_i686.whl", hash = "sha256:d6631f2e867676b13026e2846180e2c13c1e11289d67da08d71cacb2cd93d4aa"},
+ {file = "numpy-1.19.5-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:7fb43004bce0ca31d8f13a6eb5e943fa73371381e53f7074ed21a4cb786c32f8"},
+ {file = "numpy-1.19.5-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:2ea52bd92ab9f768cc64a4c3ef8f4b2580a17af0a5436f6126b08efbd1838371"},
+ {file = "numpy-1.19.5-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:400580cbd3cff6ffa6293df2278c75aef2d58d8d93d3c5614cd67981dae68ceb"},
+ {file = "numpy-1.19.5-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:df609c82f18c5b9f6cb97271f03315ff0dbe481a2a02e56aeb1b1a985ce38e60"},
+ {file = "numpy-1.19.5-cp39-cp39-win32.whl", hash = "sha256:ab83f24d5c52d60dbc8cd0528759532736b56db58adaa7b5f1f76ad551416a1e"},
+ {file = "numpy-1.19.5-cp39-cp39-win_amd64.whl", hash = "sha256:0eef32ca3132a48e43f6a0f5a82cb508f22ce5a3d6f67a8329c81c8e226d3f6e"},
+ {file = "numpy-1.19.5-pp36-pypy36_pp73-manylinux2010_x86_64.whl", hash = "sha256:a0d53e51a6cb6f0d9082decb7a4cb6dfb33055308c4c44f53103c073f649af73"},
+ {file = "numpy-1.19.5.zip", hash = "sha256:a76f502430dd98d7546e1ea2250a7360c065a5fdea52b2dffe8ae7180909b6f4"},
+ {file = "numpy-1.21.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:38e8648f9449a549a7dfe8d8755a5979b45b3538520d1e735637ef28e8c2dc50"},
+ {file = "numpy-1.21.1-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:fd7d7409fa643a91d0a05c7554dd68aa9c9bb16e186f6ccfe40d6e003156e33a"},
+ {file = "numpy-1.21.1-cp37-cp37m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:a75b4498b1e93d8b700282dc8e655b8bd559c0904b3910b144646dbbbc03e062"},
+ {file = "numpy-1.21.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1412aa0aec3e00bc23fbb8664d76552b4efde98fb71f60737c83efbac24112f1"},
+ {file = "numpy-1.21.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e46ceaff65609b5399163de5893d8f2a82d3c77d5e56d976c8b5fb01faa6b671"},
+ {file = "numpy-1.21.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:c6a2324085dd52f96498419ba95b5777e40b6bcbc20088fddb9e8cbb58885e8e"},
+ {file = "numpy-1.21.1-cp37-cp37m-win32.whl", hash = "sha256:73101b2a1fef16602696d133db402a7e7586654682244344b8329cdcbbb82172"},
+ {file = "numpy-1.21.1-cp37-cp37m-win_amd64.whl", hash = "sha256:7a708a79c9a9d26904d1cca8d383bf869edf6f8e7650d85dbc77b041e8c5a0f8"},
+ {file = "numpy-1.21.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:95b995d0c413f5d0428b3f880e8fe1660ff9396dcd1f9eedbc311f37b5652e16"},
+ {file = "numpy-1.21.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:635e6bd31c9fb3d475c8f44a089569070d10a9ef18ed13738b03049280281267"},
+ {file = "numpy-1.21.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4a3d5fb89bfe21be2ef47c0614b9c9c707b7362386c9a3ff1feae63e0267ccb6"},
+ {file = "numpy-1.21.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:8a326af80e86d0e9ce92bcc1e65c8ff88297de4fa14ee936cb2293d414c9ec63"},
+ {file = "numpy-1.21.1-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:791492091744b0fe390a6ce85cc1bf5149968ac7d5f0477288f78c89b385d9af"},
+ {file = "numpy-1.21.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0318c465786c1f63ac05d7c4dbcecd4d2d7e13f0959b01b534ea1e92202235c5"},
+ {file = "numpy-1.21.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9a513bd9c1551894ee3d31369f9b07460ef223694098cf27d399513415855b68"},
+ {file = "numpy-1.21.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:91c6f5fc58df1e0a3cc0c3a717bb3308ff850abdaa6d2d802573ee2b11f674a8"},
+ {file = "numpy-1.21.1-cp38-cp38-win32.whl", hash = "sha256:978010b68e17150db8765355d1ccdd450f9fc916824e8c4e35ee620590e234cd"},
+ {file = "numpy-1.21.1-cp38-cp38-win_amd64.whl", hash = "sha256:9749a40a5b22333467f02fe11edc98f022133ee1bfa8ab99bda5e5437b831214"},
+ {file = "numpy-1.21.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:d7a4aeac3b94af92a9373d6e77b37691b86411f9745190d2c351f410ab3a791f"},
+ {file = "numpy-1.21.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d9e7912a56108aba9b31df688a4c4f5cb0d9d3787386b87d504762b6754fbb1b"},
+ {file = "numpy-1.21.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:25b40b98ebdd272bc3020935427a4530b7d60dfbe1ab9381a39147834e985eac"},
+ {file = "numpy-1.21.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:8a92c5aea763d14ba9d6475803fc7904bda7decc2a0a68153f587ad82941fec1"},
+ {file = "numpy-1.21.1-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:05a0f648eb28bae4bcb204e6fd14603de2908de982e761a2fc78efe0f19e96e1"},
+ {file = "numpy-1.21.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f01f28075a92eede918b965e86e8f0ba7b7797a95aa8d35e1cc8821f5fc3ad6a"},
+ {file = "numpy-1.21.1-cp39-cp39-win32.whl", hash = "sha256:88c0b89ad1cc24a5efbb99ff9ab5db0f9a86e9cc50240177a571fbe9c2860ac2"},
+ {file = "numpy-1.21.1-cp39-cp39-win_amd64.whl", hash = "sha256:01721eefe70544d548425a07c80be8377096a54118070b8a62476866d5208e33"},
+ {file = "numpy-1.21.1-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:2d4d1de6e6fb3d28781c73fbde702ac97f03d79e4ffd6598b880b2d95d62ead4"},
+ {file = "numpy-1.21.1.zip", hash = "sha256:dff4af63638afcc57a3dfb9e4b26d434a7a602d225b42d746ea7fe2edf1342fd"},
+]
+scipy = [
+ {file = "scipy-1.5.4-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:4f12d13ffbc16e988fa40809cbbd7a8b45bc05ff6ea0ba8e3e41f6f4db3a9e47"},
+ {file = "scipy-1.5.4-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:a254b98dbcc744c723a838c03b74a8a34c0558c9ac5c86d5561703362231107d"},
+ {file = "scipy-1.5.4-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:368c0f69f93186309e1b4beb8e26d51dd6f5010b79264c0f1e9ca00cd92ea8c9"},
+ {file = "scipy-1.5.4-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:4598cf03136067000855d6b44d7a1f4f46994164bcd450fb2c3d481afc25dd06"},
+ {file = "scipy-1.5.4-cp36-cp36m-win32.whl", hash = "sha256:e98d49a5717369d8241d6cf33ecb0ca72deee392414118198a8e5b4c35c56340"},
+ {file = "scipy-1.5.4-cp36-cp36m-win_amd64.whl", hash = "sha256:65923bc3809524e46fb7eb4d6346552cbb6a1ffc41be748535aa502a2e3d3389"},
+ {file = "scipy-1.5.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:9ad4fcddcbf5dc67619379782e6aeef41218a79e17979aaed01ed099876c0e62"},
+ {file = "scipy-1.5.4-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:f87b39f4d69cf7d7529d7b1098cb712033b17ea7714aed831b95628f483fd012"},
+ {file = "scipy-1.5.4-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:25b241034215247481f53355e05f9e25462682b13bd9191359075682adcd9554"},
+ {file = "scipy-1.5.4-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:fa789583fc94a7689b45834453fec095245c7e69c58561dc159b5d5277057e4c"},
+ {file = "scipy-1.5.4-cp37-cp37m-win32.whl", hash = "sha256:d6d25c41a009e3c6b7e757338948d0076ee1dd1770d1c09ec131f11946883c54"},
+ {file = "scipy-1.5.4-cp37-cp37m-win_amd64.whl", hash = "sha256:2c872de0c69ed20fb1a9b9cf6f77298b04a26f0b8720a5457be08be254366c6e"},
+ {file = "scipy-1.5.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:e360cb2299028d0b0d0f65a5c5e51fc16a335f1603aa2357c25766c8dab56938"},
+ {file = "scipy-1.5.4-cp38-cp38-manylinux1_i686.whl", hash = "sha256:3397c129b479846d7eaa18f999369a24322d008fac0782e7828fa567358c36ce"},
+ {file = "scipy-1.5.4-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:168c45c0c32e23f613db7c9e4e780bc61982d71dcd406ead746c7c7c2f2004ce"},
+ {file = "scipy-1.5.4-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:213bc59191da2f479984ad4ec39406bf949a99aba70e9237b916ce7547b6ef42"},
+ {file = "scipy-1.5.4-cp38-cp38-win32.whl", hash = "sha256:634568a3018bc16a83cda28d4f7aed0d803dd5618facb36e977e53b2df868443"},
+ {file = "scipy-1.5.4-cp38-cp38-win_amd64.whl", hash = "sha256:b03c4338d6d3d299e8ca494194c0ae4f611548da59e3c038813f1a43976cb437"},
+ {file = "scipy-1.5.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3d5db5d815370c28d938cf9b0809dade4acf7aba57eaf7ef733bfedc9b2474c4"},
+ {file = "scipy-1.5.4-cp39-cp39-manylinux1_i686.whl", hash = "sha256:6b0ceb23560f46dd236a8ad4378fc40bad1783e997604ba845e131d6c680963e"},
+ {file = "scipy-1.5.4-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:ed572470af2438b526ea574ff8f05e7f39b44ac37f712105e57fc4d53a6fb660"},
+ {file = "scipy-1.5.4-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:8c8d6ca19c8497344b810b0b0344f8375af5f6bb9c98bd42e33f747417ab3f57"},
+ {file = "scipy-1.5.4-cp39-cp39-win32.whl", hash = "sha256:d84cadd7d7998433334c99fa55bcba0d8b4aeff0edb123b2a1dfcface538e474"},
+ {file = "scipy-1.5.4-cp39-cp39-win_amd64.whl", hash = "sha256:cc1f78ebc982cd0602c9a7615d878396bec94908db67d4ecddca864d049112f2"},
+ {file = "scipy-1.5.4.tar.gz", hash = "sha256:4a453d5e5689de62e5d38edf40af3f17560bfd63c9c5bd228c18c1f99afa155b"},
+ {file = "scipy-1.6.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a15a1f3fc0abff33e792d6049161b7795909b40b97c6cc2934ed54384017ab76"},
+ {file = "scipy-1.6.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:e79570979ccdc3d165456dd62041d9556fb9733b86b4b6d818af7a0afc15f092"},
+ {file = "scipy-1.6.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:a423533c55fec61456dedee7b6ee7dce0bb6bfa395424ea374d25afa262be261"},
+ {file = "scipy-1.6.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:33d6b7df40d197bdd3049d64e8e680227151673465e5d85723b3b8f6b15a6ced"},
+ {file = "scipy-1.6.1-cp37-cp37m-win32.whl", hash = "sha256:6725e3fbb47da428794f243864f2297462e9ee448297c93ed1dcbc44335feb78"},
+ {file = "scipy-1.6.1-cp37-cp37m-win_amd64.whl", hash = "sha256:5fa9c6530b1661f1370bcd332a1e62ca7881785cc0f80c0d559b636567fab63c"},
+ {file = "scipy-1.6.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:bd50daf727f7c195e26f27467c85ce653d41df4358a25b32434a50d8870fc519"},
+ {file = "scipy-1.6.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:f46dd15335e8a320b0fb4685f58b7471702234cba8bb3442b69a3e1dc329c345"},
+ {file = "scipy-1.6.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:0e5b0ccf63155d90da576edd2768b66fb276446c371b73841e3503be1d63fb5d"},
+ {file = "scipy-1.6.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:2481efbb3740977e3c831edfd0bd9867be26387cacf24eb5e366a6a374d3d00d"},
+ {file = "scipy-1.6.1-cp38-cp38-win32.whl", hash = "sha256:68cb4c424112cd4be886b4d979c5497fba190714085f46b8ae67a5e4416c32b4"},
+ {file = "scipy-1.6.1-cp38-cp38-win_amd64.whl", hash = "sha256:5f331eeed0297232d2e6eea51b54e8278ed8bb10b099f69c44e2558c090d06bf"},
+ {file = "scipy-1.6.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:0c8a51d33556bf70367452d4d601d1742c0e806cd0194785914daf19775f0e67"},
+ {file = "scipy-1.6.1-cp39-cp39-manylinux1_i686.whl", hash = "sha256:83bf7c16245c15bc58ee76c5418e46ea1811edcc2e2b03041b804e46084ab627"},
+ {file = "scipy-1.6.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:794e768cc5f779736593046c9714e0f3a5940bc6dcc1dba885ad64cbfb28e9f0"},
+ {file = "scipy-1.6.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:5da5471aed911fe7e52b86bf9ea32fb55ae93e2f0fac66c32e58897cfb02fa07"},
+ {file = "scipy-1.6.1-cp39-cp39-win32.whl", hash = "sha256:8e403a337749ed40af60e537cc4d4c03febddcc56cd26e774c9b1b600a70d3e4"},
+ {file = "scipy-1.6.1-cp39-cp39-win_amd64.whl", hash = "sha256:a5193a098ae9f29af283dcf0041f762601faf2e595c0db1da929875b7570353f"},
+ {file = "scipy-1.6.1.tar.gz", hash = "sha256:c4fceb864890b6168e79b0e714c585dbe2fd4222768ee90bc1aa0f8218691b11"},
+]
diff --git a/uv/spec/fixtures/projects/poetry/multiple_requirements/pyproject.toml b/uv/spec/fixtures/projects/poetry/multiple_requirements/pyproject.toml
new file mode 100644
index 00000000000..33bf0ee866c
--- /dev/null
+++ b/uv/spec/fixtures/projects/poetry/multiple_requirements/pyproject.toml
@@ -0,0 +1,14 @@
+[tool.poetry]
+name = "example"
+version = "0.1.0"
+description = ""
+authors = []
+
+[tool.poetry.dependencies]
+numpy = [
+ { version = "^1.19", python = "^3.6,<3.7" },
+ { version = "^1.20", python = "^3.7" }]
+scipy = [
+ { version = "^1.5", python = "^3.6,<3.7" },
+ { version = "^1.6.0", python = "^3.7" }
+]
diff --git a/uv/spec/fixtures/projects/poetry/relative_path/my-project/pyproject.toml b/uv/spec/fixtures/projects/poetry/relative_path/my-project/pyproject.toml
new file mode 100644
index 00000000000..e178f91a7a5
--- /dev/null
+++ b/uv/spec/fixtures/projects/poetry/relative_path/my-project/pyproject.toml
@@ -0,0 +1,16 @@
+[tool.poetry]
+name = "my-project"
+version = "0.1.0"
+description = ""
+authors = []
+license = ""
+packages = [
+ {include = "src"},
+]
+
+[tool.poetry.dependencies]
+python = "^3.9"
+
+[build-system]
+requires = ["poetry>=1.0"]
+build-backend = "poetry.masonry.api"
diff --git a/uv/spec/fixtures/projects/poetry/relative_path/my-project/src/__init__.py b/uv/spec/fixtures/projects/poetry/relative_path/my-project/src/__init__.py
new file mode 100644
index 00000000000..b794fd409a5
--- /dev/null
+++ b/uv/spec/fixtures/projects/poetry/relative_path/my-project/src/__init__.py
@@ -0,0 +1 @@
+__version__ = '0.1.0'
diff --git a/uv/spec/fixtures/projects/poetry/relative_path/poetry.lock b/uv/spec/fixtures/projects/poetry/relative_path/poetry.lock
new file mode 100644
index 00000000000..964b8446b09
--- /dev/null
+++ b/uv/spec/fixtures/projects/poetry/relative_path/poetry.lock
@@ -0,0 +1,125 @@
+[[package]]
+name = "my-project"
+version = "0.1.0"
+description = ""
+category = "main"
+optional = false
+python-versions = "^3.9"
+develop = true
+
+[package.source]
+type = "directory"
+url = "my-project"
+
+[[package]]
+name = "mypy"
+version = "0.812"
+description = "Optional static typing for Python"
+category = "dev"
+optional = false
+python-versions = ">=3.5"
+
+[package.dependencies]
+mypy-extensions = ">=0.4.3,<0.5.0"
+typed-ast = ">=1.4.0,<1.5.0"
+typing-extensions = ">=3.7.4"
+
+[package.extras]
+dmypy = ["psutil (>=4.0)"]
+
+[[package]]
+name = "mypy-extensions"
+version = "0.4.3"
+description = "Experimental type system extensions for programs checked with the mypy typechecker."
+category = "dev"
+optional = false
+python-versions = "*"
+
+[[package]]
+name = "typed-ast"
+version = "1.4.3"
+description = "a fork of Python 2 and 3 ast modules with type comment support"
+category = "dev"
+optional = false
+python-versions = "*"
+
+[[package]]
+name = "typing-extensions"
+version = "3.10.0.0"
+description = "Backported and Experimental Type Hints for Python 3.5+"
+category = "dev"
+optional = false
+python-versions = "*"
+
+[metadata]
+lock-version = "1.1"
+python-versions = "^3.9"
+content-hash = "576e8f718ba25d0b4762e64eb13fc8e3bdb94144eb58d88dd7a61b1ed7da7a1d"
+
+[metadata.files]
+my-project = []
+mypy = [
+ {file = "mypy-0.812-cp35-cp35m-macosx_10_9_x86_64.whl", hash = "sha256:a26f8ec704e5a7423c8824d425086705e381b4f1dfdef6e3a1edab7ba174ec49"},
+ {file = "mypy-0.812-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:28fb5479c494b1bab244620685e2eb3c3f988d71fd5d64cc753195e8ed53df7c"},
+ {file = "mypy-0.812-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:9743c91088d396c1a5a3c9978354b61b0382b4e3c440ce83cf77994a43e8c521"},
+ {file = "mypy-0.812-cp35-cp35m-win_amd64.whl", hash = "sha256:d7da2e1d5f558c37d6e8c1246f1aec1e7349e4913d8fb3cb289a35de573fe2eb"},
+ {file = "mypy-0.812-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:4eec37370483331d13514c3f55f446fc5248d6373e7029a29ecb7b7494851e7a"},
+ {file = "mypy-0.812-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:d65cc1df038ef55a99e617431f0553cd77763869eebdf9042403e16089fe746c"},
+ {file = "mypy-0.812-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:61a3d5b97955422964be6b3baf05ff2ce7f26f52c85dd88db11d5e03e146a3a6"},
+ {file = "mypy-0.812-cp36-cp36m-win_amd64.whl", hash = "sha256:25adde9b862f8f9aac9d2d11971f226bd4c8fbaa89fb76bdadb267ef22d10064"},
+ {file = "mypy-0.812-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:552a815579aa1e995f39fd05dde6cd378e191b063f031f2acfe73ce9fb7f9e56"},
+ {file = "mypy-0.812-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:499c798053cdebcaa916eef8cd733e5584b5909f789de856b482cd7d069bdad8"},
+ {file = "mypy-0.812-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:5873888fff1c7cf5b71efbe80e0e73153fe9212fafdf8e44adfe4c20ec9f82d7"},
+ {file = "mypy-0.812-cp37-cp37m-win_amd64.whl", hash = "sha256:9f94aac67a2045ec719ffe6111df543bac7874cee01f41928f6969756e030564"},
+ {file = "mypy-0.812-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d23e0ea196702d918b60c8288561e722bf437d82cb7ef2edcd98cfa38905d506"},
+ {file = "mypy-0.812-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:674e822aa665b9fd75130c6c5f5ed9564a38c6cea6a6432ce47eafb68ee578c5"},
+ {file = "mypy-0.812-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:abf7e0c3cf117c44d9285cc6128856106183938c68fd4944763003decdcfeb66"},
+ {file = "mypy-0.812-cp38-cp38-win_amd64.whl", hash = "sha256:0d0a87c0e7e3a9becdfbe936c981d32e5ee0ccda3e0f07e1ef2c3d1a817cf73e"},
+ {file = "mypy-0.812-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7ce3175801d0ae5fdfa79b4f0cfed08807af4d075b402b7e294e6aa72af9aa2a"},
+ {file = "mypy-0.812-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:b09669bcda124e83708f34a94606e01b614fa71931d356c1f1a5297ba11f110a"},
+ {file = "mypy-0.812-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:33f159443db0829d16f0a8d83d94df3109bb6dd801975fe86bacb9bf71628e97"},
+ {file = "mypy-0.812-cp39-cp39-win_amd64.whl", hash = "sha256:3f2aca7f68580dc2508289c729bd49ee929a436208d2b2b6aab15745a70a57df"},
+ {file = "mypy-0.812-py3-none-any.whl", hash = "sha256:2f9b3407c58347a452fc0736861593e105139b905cca7d097e413453a1d650b4"},
+ {file = "mypy-0.812.tar.gz", hash = "sha256:cd07039aa5df222037005b08fbbfd69b3ab0b0bd7a07d7906de75ae52c4e3119"},
+]
+mypy-extensions = [
+ {file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"},
+ {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"},
+]
+typed-ast = [
+ {file = "typed_ast-1.4.3-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:2068531575a125b87a41802130fa7e29f26c09a2833fea68d9a40cf33902eba6"},
+ {file = "typed_ast-1.4.3-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:c907f561b1e83e93fad565bac5ba9c22d96a54e7ea0267c708bffe863cbe4075"},
+ {file = "typed_ast-1.4.3-cp35-cp35m-manylinux2014_aarch64.whl", hash = "sha256:1b3ead4a96c9101bef08f9f7d1217c096f31667617b58de957f690c92378b528"},
+ {file = "typed_ast-1.4.3-cp35-cp35m-win32.whl", hash = "sha256:dde816ca9dac1d9c01dd504ea5967821606f02e510438120091b84e852367428"},
+ {file = "typed_ast-1.4.3-cp35-cp35m-win_amd64.whl", hash = "sha256:777a26c84bea6cd934422ac2e3b78863a37017618b6e5c08f92ef69853e765d3"},
+ {file = "typed_ast-1.4.3-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:f8afcf15cc511ada719a88e013cec87c11aff7b91f019295eb4530f96fe5ef2f"},
+ {file = "typed_ast-1.4.3-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:52b1eb8c83f178ab787f3a4283f68258525f8d70f778a2f6dd54d3b5e5fb4341"},
+ {file = "typed_ast-1.4.3-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:01ae5f73431d21eead5015997ab41afa53aa1fbe252f9da060be5dad2c730ace"},
+ {file = "typed_ast-1.4.3-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:c190f0899e9f9f8b6b7863debfb739abcb21a5c054f911ca3596d12b8a4c4c7f"},
+ {file = "typed_ast-1.4.3-cp36-cp36m-win32.whl", hash = "sha256:398e44cd480f4d2b7ee8d98385ca104e35c81525dd98c519acff1b79bdaac363"},
+ {file = "typed_ast-1.4.3-cp36-cp36m-win_amd64.whl", hash = "sha256:bff6ad71c81b3bba8fa35f0f1921fb24ff4476235a6e94a26ada2e54370e6da7"},
+ {file = "typed_ast-1.4.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0fb71b8c643187d7492c1f8352f2c15b4c4af3f6338f21681d3681b3dc31a266"},
+ {file = "typed_ast-1.4.3-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:760ad187b1041a154f0e4d0f6aae3e40fdb51d6de16e5c99aedadd9246450e9e"},
+ {file = "typed_ast-1.4.3-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:5feca99c17af94057417d744607b82dd0a664fd5e4ca98061480fd8b14b18d04"},
+ {file = "typed_ast-1.4.3-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:95431a26309a21874005845c21118c83991c63ea800dd44843e42a916aec5899"},
+ {file = "typed_ast-1.4.3-cp37-cp37m-win32.whl", hash = "sha256:aee0c1256be6c07bd3e1263ff920c325b59849dc95392a05f258bb9b259cf39c"},
+ {file = "typed_ast-1.4.3-cp37-cp37m-win_amd64.whl", hash = "sha256:9ad2c92ec681e02baf81fdfa056fe0d818645efa9af1f1cd5fd6f1bd2bdfd805"},
+ {file = "typed_ast-1.4.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b36b4f3920103a25e1d5d024d155c504080959582b928e91cb608a65c3a49e1a"},
+ {file = "typed_ast-1.4.3-cp38-cp38-manylinux1_i686.whl", hash = "sha256:067a74454df670dcaa4e59349a2e5c81e567d8d65458d480a5b3dfecec08c5ff"},
+ {file = "typed_ast-1.4.3-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:7538e495704e2ccda9b234b82423a4038f324f3a10c43bc088a1636180f11a41"},
+ {file = "typed_ast-1.4.3-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:af3d4a73793725138d6b334d9d247ce7e5f084d96284ed23f22ee626a7b88e39"},
+ {file = "typed_ast-1.4.3-cp38-cp38-win32.whl", hash = "sha256:f2362f3cb0f3172c42938946dbc5b7843c2a28aec307c49100c8b38764eb6927"},
+ {file = "typed_ast-1.4.3-cp38-cp38-win_amd64.whl", hash = "sha256:dd4a21253f42b8d2b48410cb31fe501d32f8b9fbeb1f55063ad102fe9c425e40"},
+ {file = "typed_ast-1.4.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f328adcfebed9f11301eaedfa48e15bdece9b519fb27e6a8c01aa52a17ec31b3"},
+ {file = "typed_ast-1.4.3-cp39-cp39-manylinux1_i686.whl", hash = "sha256:2c726c276d09fc5c414693a2de063f521052d9ea7c240ce553316f70656c84d4"},
+ {file = "typed_ast-1.4.3-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:cae53c389825d3b46fb37538441f75d6aecc4174f615d048321b716df2757fb0"},
+ {file = "typed_ast-1.4.3-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:b9574c6f03f685070d859e75c7f9eeca02d6933273b5e69572e5ff9d5e3931c3"},
+ {file = "typed_ast-1.4.3-cp39-cp39-win32.whl", hash = "sha256:209596a4ec71d990d71d5e0d312ac935d86930e6eecff6ccc7007fe54d703808"},
+ {file = "typed_ast-1.4.3-cp39-cp39-win_amd64.whl", hash = "sha256:9c6d1a54552b5330bc657b7ef0eae25d00ba7ffe85d9ea8ae6540d2197a3788c"},
+ {file = "typed_ast-1.4.3.tar.gz", hash = "sha256:fb1bbeac803adea29cedd70781399c99138358c26d05fcbd23c13016b7f5ec65"},
+]
+typing-extensions = [
+ {file = "typing_extensions-3.10.0.0-py2-none-any.whl", hash = "sha256:0ac0f89795dd19de6b97debb0c6af1c70987fd80a2d62d1958f7e56fcc31b497"},
+ {file = "typing_extensions-3.10.0.0-py3-none-any.whl", hash = "sha256:779383f6086d90c99ae41cf0ff39aac8a7937a9283ce0a414e5dd782f4c94a84"},
+ {file = "typing_extensions-3.10.0.0.tar.gz", hash = "sha256:50b6f157849174217d0656f99dc82fe932884fb250826c18350e159ec6cdf342"},
+]
diff --git a/uv/spec/fixtures/projects/poetry/relative_path/pyproject.toml b/uv/spec/fixtures/projects/poetry/relative_path/pyproject.toml
new file mode 100644
index 00000000000..145e68bf9e0
--- /dev/null
+++ b/uv/spec/fixtures/projects/poetry/relative_path/pyproject.toml
@@ -0,0 +1,17 @@
+[tool.poetry]
+name = "example"
+version = "0.1.0"
+description = ""
+authors = []
+license = ""
+
+[tool.poetry.dependencies]
+python = "^3.9"
+my-project = {path = "my-project", develop = true}
+
+[tool.poetry.dev-dependencies]
+mypy = "^0.812"
+
+[build-system]
+requires = ["poetry-core>=1.0.0"]
+build-backend = "poetry.core.masonry.api"
diff --git a/uv/spec/fixtures/projects/unresolvable/requirements.in b/uv/spec/fixtures/projects/unresolvable/requirements.in
new file mode 100644
index 00000000000..8e44befaec3
--- /dev/null
+++ b/uv/spec/fixtures/projects/unresolvable/requirements.in
@@ -0,0 +1,21 @@
+#
+# requirements.in - explicit python dependencies
+#
+# to update requirements.txt, run:
+#
+# pip-compile requirements.in
+#
+
+pip
+jupyter
+jupyter_contrib_nbextensions
+jupyter_nbextensions_configurator
+
+librosa
+numba==0.48
+numpy==1.26.4
+
+jax
+matplotlib
+tqdm
+voila==0.1.21
diff --git a/uv/spec/fixtures/projects/unresolvable/requirements.txt b/uv/spec/fixtures/projects/unresolvable/requirements.txt
new file mode 100644
index 00000000000..cedcdb127ca
--- /dev/null
+++ b/uv/spec/fixtures/projects/unresolvable/requirements.txt
@@ -0,0 +1,91 @@
+#
+# This file is autogenerated by pip-compile
+# To update, run:
+#
+# pip-compile requirements.in
+#
+absl-py==0.9.0 # via jax
+appnope==0.1.0 # via ipykernel, ipython
+async-generator==1.10 # via voila
+attrs==19.3.0 # via jsonschema
+audioread==2.1.8 # via librosa
+backcall==0.2.0 # via ipython
+bleach==3.1.5 # via nbconvert
+cffi==1.14.0 # via soundfile
+cycler==0.10.0 # via matplotlib
+decorator==4.4.2 # via ipython, librosa, traitlets
+defusedxml==0.6.0 # via nbconvert
+entrypoints==0.3 # via nbconvert
+importlib-metadata==1.7.0 # via jsonschema
+ipykernel==5.3.3 # via ipywidgets, jupyter, jupyter-console, jupyter-server, notebook, qtconsole
+ipython-genutils==0.2.0 # via jupyter-contrib-nbextensions, jupyter-server, nbformat, notebook, qtconsole, traitlets
+ipython==7.16.1 # via ipykernel, ipywidgets, jupyter-console, jupyter-latex-envs
+ipywidgets==7.5.1 # via jupyter
+jax==0.1.72 # via -r requirements.in
+jedi==0.17.2 # via ipython
+jinja2==2.11.2 # via jupyter-server, nbconvert, notebook
+joblib==0.16.0 # via librosa, scikit-learn
+jsonschema==3.2.0 # via nbformat
+jupyter-client==6.1.6 # via ipykernel, jupyter-console, jupyter-server, notebook, qtconsole
+jupyter-console==6.1.0 # via jupyter
+jupyter-contrib-core==0.3.3 # via jupyter-contrib-nbextensions, jupyter-nbextensions-configurator
+jupyter-contrib-nbextensions==0.5.1 # via -r requirements.in
+jupyter-core==4.6.3 # via jupyter-client, jupyter-contrib-core, jupyter-contrib-nbextensions, jupyter-latex-envs, jupyter-nbextensions-configurator, jupyter-server, nbconvert, nbformat, notebook, qtconsole
+jupyter-highlight-selected-word==0.2.0 # via jupyter-contrib-nbextensions
+jupyter-latex-envs==1.4.6 # via jupyter-contrib-nbextensions
+jupyter-nbextensions-configurator==0.4.1 # via -r requirements.in, jupyter-contrib-nbextensions
+jupyter-server==0.1.1 # via voila
+jupyter==1.0.0 # via -r requirements.in
+jupyterlab-pygments==0.1.1 # via voila
+kiwisolver==1.2.0 # via matplotlib
+librosa==0.7.2 # via -r requirements.in
+llvmlite==0.31.0 # via numba
+lxml==4.5.2 # via jupyter-contrib-nbextensions
+markupsafe==1.1.1 # via jinja2
+matplotlib==3.5.0 # via -r requirements.in
+mistune==0.8.4 # via nbconvert
+nbconvert==5.6.1 # via jupyter, jupyter-contrib-nbextensions, jupyter-latex-envs, jupyter-server, notebook, voila
+nbformat==5.0.7 # via ipywidgets, jupyter-server, nbconvert, notebook
+notebook==6.0.3 # via jupyter, jupyter-contrib-core, jupyter-contrib-nbextensions, jupyter-latex-envs, jupyter-nbextensions-configurator, widgetsnbextension
+numba==0.48.0 # via -r requirements.in, librosa, resampy
+numpy==1.19.0 # via -r requirements.in, jax, librosa, matplotlib, numba, opt-einsum, resampy, scikit-learn, scipy
+opt-einsum==3.2.1 # via jax
+packaging==20.4 # via bleach
+pandocfilters==1.4.2 # via nbconvert
+parso==0.7.0 # via jedi
+pexpect==4.8.0 # via ipython
+pickleshare==0.7.5 # via ipython
+pillow==7.2.0 # via matplotlib
+prometheus-client==0.8.0 # via jupyter-server, notebook
+prompt-toolkit==3.0.5 # via ipython, jupyter-console
+ptyprocess==0.6.0 # via pexpect, terminado
+pycparser==2.20 # via cffi
+pygments==2.6.1 # via ipython, jupyter-console, jupyterlab-pygments, nbconvert, qtconsole, voila
+pyparsing==2.4.7 # via matplotlib, packaging
+pyrsistent==0.16.0 # via jsonschema
+python-dateutil==2.8.1 # via jupyter-client, matplotlib
+pyyaml==5.3.1 # via jupyter-contrib-nbextensions, jupyter-nbextensions-configurator
+pyzmq==19.0.1 # via jupyter-client, jupyter-server, notebook, qtconsole
+qtconsole==4.7.5 # via jupyter
+qtpy==1.9.0 # via qtconsole
+resampy==0.2.2 # via librosa
+scikit-learn==0.23.1 # via librosa
+scipy==1.5.1 # via librosa, resampy, scikit-learn
+send2trash==1.5.0 # via jupyter-server, notebook
+six==1.15.0 # via absl-py, bleach, cycler, jsonschema, librosa, packaging, pyrsistent, python-dateutil, resampy, traitlets
+soundfile==0.10.3.post1 # via librosa
+terminado==0.8.3 # via jupyter-server, notebook
+testpath==0.4.4 # via nbconvert
+threadpoolctl==2.1.0 # via scikit-learn
+tornado==6.0.4 # via ipykernel, jupyter-client, jupyter-contrib-core, jupyter-contrib-nbextensions, jupyter-nbextensions-configurator, jupyter-server, notebook, terminado
+tqdm==4.48.0 # via -r requirements.in
+traitlets==4.3.3 # via ipykernel, ipython, ipywidgets, jupyter-client, jupyter-contrib-core, jupyter-contrib-nbextensions, jupyter-core, jupyter-latex-envs, jupyter-nbextensions-configurator, jupyter-server, nbconvert, nbformat, notebook, qtconsole
+voila==0.1.21 # via -r requirements.in
+wcwidth==0.2.5 # via prompt-toolkit
+webencodings==0.5.1 # via bleach
+widgetsnbextension==3.5.1 # via ipywidgets
+zipp==3.1.0 # via importlib-metadata
+
+# The following packages are considered to be unsafe in a requirements file:
+# pip
+# setuptools
diff --git a/uv/spec/fixtures/psycopg_homepage.html b/uv/spec/fixtures/psycopg_homepage.html
new file mode 100644
index 00000000000..23897fb46cb
--- /dev/null
+++ b/uv/spec/fixtures/psycopg_homepage.html
@@ -0,0 +1,229 @@
+
+
+
+ PostgreSQL + Python | Psycopg
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/uv/spec/fixtures/pypi/pypi_response.json b/uv/spec/fixtures/pypi/pypi_response.json
new file mode 100644
index 00000000000..9ac548c6f84
--- /dev/null
+++ b/uv/spec/fixtures/pypi/pypi_response.json
@@ -0,0 +1,677 @@
+{
+ "info": {
+ "maintainer": "",
+ "docs_url": null,
+ "requires_python": "",
+ "maintainer_email": "",
+ "cheesecake_code_kwalitee_id": null,
+ "keywords": "",
+ "package_url": "http://pypi.org/pypi/luigi",
+ "author": "The Luigi Authors",
+ "author_email": "",
+ "download_url": "",
+ "platform": "",
+ "version": "2.6.0",
+ "cheesecake_documentation_id": null,
+ "_pypi_hidden": false,
+ "description": ".. note::\n\n For the latest source, discussion, etc, please visit the\n `GitHub repository `_\n\n\n.. figure:: https://raw.githubusercontent.com/spotify/luigi/master/doc/luigi.png\n :alt: Luigi Logo\n :align: center\n\n.. image:: https://img.shields.io/travis/spotify/luigi/master.svg?style=flat\n :target: https://travis-ci.org/spotify/luigi\n\n.. image:: https://img.shields.io/codecov/c/github/spotify/luigi/master.svg?style=flat\n :target: https://codecov.io/gh/spotify/luigi?branch=master\n\n.. image:: https://landscape.io/github/spotify/luigi/master/landscape.svg?style=flat\n :target: https://landscape.io/github/spotify/luigi/master\n\n.. image:: https://img.shields.io/pypi/v/luigi.svg?style=flat\n :target: https://pypi.org/pypi/luigi\n\n.. image:: https://img.shields.io/pypi/l/luigi.svg?style=flat\n :target: https://pypi.org/pypi/luigi\n\nLuigi is a Python (2.7, 3.3, 3.4, 3.5) package that helps you build complex pipelines of batch\njobs. It handles dependency resolution, workflow management, visualization,\nhandling failures, command line integration, and much more.\n\nGetting Started\n---------------\n\nRun ``pip install luigi`` to install the latest stable version from `PyPI\n`_. Documentation for the latest release is\nhosted `here `__.\n\nFor the bleeding edge code, ``pip install\ngit+https://github.com/spotify/luigi.git``. Bleeding edge documentation can be\nfound `here `__.\n\nBackground\n----------\n\nThe purpose of Luigi is to address all the plumbing typically associated\nwith long-running batch processes. You want to chain many tasks,\nautomate them, and failures *will* happen. These tasks can be anything,\nbut are typically long running things like\n`Hadoop `_ jobs, dumping data to/from\ndatabases, running machine learning algorithms, or anything else.\n\nThere are other software packages that focus on lower level aspects of\ndata processing, like `Hive `__,\n`Pig `_, or\n`Cascading `_. Luigi is not a framework to\nreplace these. Instead it helps you stitch many tasks together, where\neach task can be a `Hive query `__,\na `Hadoop job in Java `_,\na `Spark job in Scala or Python `_\na Python snippet,\n`dumping a table `_\nfrom a database, or anything else. It's easy to build up\nlong-running pipelines that comprise thousands of tasks and take days or\nweeks to complete. Luigi takes care of a lot of the workflow management\nso that you can focus on the tasks themselves and their dependencies.\n\nYou can build pretty much any task you want, but Luigi also comes with a\n*toolbox* of several common task templates that you use. It includes\nsupport for running\n`Python mapreduce jobs `_\nin Hadoop, as well as\n`Hive `__,\nand `Pig `__,\njobs. It also comes with\n`file system abstractions for HDFS `_,\nand local files that ensures all file system operations are atomic. This\nis important because it means your data pipeline will not crash in a\nstate containing partial data.\n\nVisualiser page\n---------------\n\nThe Luigi server comes with a web interface too, so you can search and filter\namong all your tasks.\n\n.. figure:: https://raw.githubusercontent.com/spotify/luigi/master/doc/visualiser_front_page.png\n :alt: Visualiser page\n\nDependency graph example\n------------------------\n\nJust to give you an idea of what Luigi does, this is a screen shot from\nsomething we are running in production. Using Luigi's visualiser, we get\na nice visual overview of the dependency graph of the workflow. Each\nnode represents a task which has to be run. Green tasks are already\ncompleted whereas yellow tasks are yet to be run. Most of these tasks\nare Hadoop jobs, but there are also some things that run locally and\nbuild up data files.\n\n.. figure:: https://raw.githubusercontent.com/spotify/luigi/master/doc/user_recs.png\n :alt: Dependency graph\n\nPhilosophy\n----------\n\nConceptually, Luigi is similar to `GNU\nMake `_ where you have certain tasks\nand these tasks in turn may have dependencies on other tasks. There are\nalso some similarities to `Oozie `_\nand `Azkaban `_. One major\ndifference is that Luigi is not just built specifically for Hadoop, and\nit's easy to extend it with other kinds of tasks.\n\nEverything in Luigi is in Python. Instead of XML configuration or\nsimilar external data files, the dependency graph is specified *within\nPython*. This makes it easy to build up complex dependency graphs of\ntasks, where the dependencies can involve date algebra or recursive\nreferences to other versions of the same task. However, the workflow can\ntrigger things not in Python, such as running\n`Pig scripts `_\nor `scp'ing files `_.\n\nWho uses Luigi?\n---------------\n\nWe use Luigi internally at `Spotify `_ to run\nthousands of tasks every day, organized in complex dependency graphs.\nMost of these tasks are Hadoop jobs. Luigi provides an infrastructure\nthat powers all kinds of stuff including recommendations, toplists, A/B\ntest analysis, external reports, internal dashboards, etc.\n\nSince Luigi is open source and without any registration walls, the exact number\nof Luigi users is unknown. But based on the number of unique contributors, we\nexpect hundreds of enterprises to use it. Some users have written blog posts\nor held presentations about Luigi:\n\n* `Spotify (NYC Data Science) `_\n* `Foursquare `_\n* `Mortar Data `_\n* `Stripe `_\n* `Asana `_\n* `Buffer `_\n* `SeatGeek `_\n* `Treasure Data `_\n* `Growth Intelligence `_\n* `AdRoll `_\n* `Schibsted `_\n* `17zuoye `_\n* `enbrite.ly `_\n* `Dow Jones / The Wall Street Journal `_\n* `Hotels.com `_\n* `Custobar (Metrics Monday Helsinki) `_\n* `Blendle `_\n* `TrustYou (PyData Berlin 2015) `_\n* `Groupon / OrderUp `_\n\nWe're more than happy to have your company added here. Just send a PR on GitHub.\n\nExternal links\n--------------\n\n* `Mailing List `_ for discussions and asking questions. (Google Groups)\n* `Releases `_ (PyPI)\n* `Source code `_ (Github)\n* `Hubot Integration `_ plugin for Slack, Hipchat, etc (Github)\n\nAuthors\n-------\n\nLuigi was built at `Spotify `_, mainly by\n`Erik Bernhardsson `_ and\n`Elias Freider `_.\n`Many other people `_\nhave contributed since open sourcing in late 2012.\n`Arash Rouhani `_ is currently the chief\nmaintainer of Luigi.\n",
+ "release_url": "http://pypi.org/pypi/luigi/2.6.0",
+ "downloads": {
+ "last_month": 0,
+ "last_week": 0,
+ "last_day": 0
+ },
+ "_pypi_ordering": 41,
+ "classifiers": [
+ "Development Status :: 5 - Production/Stable",
+ "Environment :: Console",
+ "Environment :: Web Environment",
+ "Intended Audience :: Developers",
+ "Intended Audience :: System Administrators",
+ "License :: OSI Approved :: Apache Software License",
+ "Programming Language :: Python :: 2.7",
+ "Programming Language :: Python :: 3.3",
+ "Programming Language :: Python :: 3.4",
+ "Programming Language :: Python :: 3.5",
+ "Topic :: System :: Monitoring"
+ ],
+ "bugtrack_url": null,
+ "name": "luigi",
+ "license": "Apache License 2.0",
+ "summary": "Workflow mgmgt + task scheduling + dependency resolution",
+ "home_page": "https://github.com/spotify/luigi",
+ "cheesecake_installability_id": null
+ },
+ "releases": {
+ "1.1.1": [
+ {
+ "has_sig": false,
+ "upload_time": "2015-03-16T13:02:09",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/59/d2/5f32dc62bfa1b430cb902bcd26c652f9fe4c9462a3b06bc1ca6e80127d85/luigi-1.1.1.tar.gz",
+ "md5_digest": "5659011287f08ff6f1a36f9b9ab04269",
+ "downloads": 2776,
+ "filename": "luigi-1.1.1.tar.gz",
+ "packagetype": "sdist",
+ "path": "59/d2/5f32dc62bfa1b430cb902bcd26c652f9fe4c9462a3b06bc1ca6e80127d85/luigi-1.1.1.tar.gz",
+ "size": 357235
+ }
+ ],
+ "1.1.0": [
+ {
+ "has_sig": false,
+ "upload_time": "2015-03-07T17:29:44",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/85/b8/7a89ec0981570ae1fd30f102c8410381770db7898bbfdea3e1aa3ddd3b43/luigi-1.1.0.tar.gz",
+ "md5_digest": "742e9d7acbdceb007c5280b9e9f0f00d",
+ "downloads": 2713,
+ "filename": "luigi-1.1.0.tar.gz",
+ "packagetype": "sdist",
+ "path": "85/b8/7a89ec0981570ae1fd30f102c8410381770db7898bbfdea3e1aa3ddd3b43/luigi-1.1.0.tar.gz",
+ "size": 349728
+ }
+ ],
+ "1.0.6": [
+ {
+ "has_sig": false,
+ "upload_time": "2013-08-07T23:47:21",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/e9/3d/68c6ca27f4bda9aabfef3c58c2866cf5db6e05524162d36b3adb4e8fa8e5/luigi-1.0.6.tar.gz",
+ "md5_digest": "173f1868d0f8c318b2f9e91036d9bff2",
+ "downloads": 2153,
+ "filename": "luigi-1.0.6.tar.gz",
+ "packagetype": "sdist",
+ "path": "e9/3d/68c6ca27f4bda9aabfef3c58c2866cf5db6e05524162d36b3adb4e8fa8e5/luigi-1.0.6.tar.gz",
+ "size": 225527
+ }
+ ],
+ "1.1.2": [
+ {
+ "has_sig": false,
+ "upload_time": "2015-03-18T00:50:52",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/3d/26/191da8144fd2a881f72c6d87df68ee654e684989dcaa3559dcbc9c0a6355/luigi-1.1.2.tar.gz",
+ "md5_digest": "a617f82f1354c49cb227b7877d3defa2",
+ "downloads": 44221,
+ "filename": "luigi-1.1.2.tar.gz",
+ "packagetype": "sdist",
+ "path": "3d/26/191da8144fd2a881f72c6d87df68ee654e684989dcaa3559dcbc9c0a6355/luigi-1.1.2.tar.gz",
+ "size": 357305
+ }
+ ],
+ "1.0.5": [
+ {
+ "has_sig": false,
+ "upload_time": "2013-08-07T23:44:22",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/8c/16/4ac01f87ecb5f1cd1b083003cdaa485f1d4445817dd67fa4145d35243936/luigi-1.0.5.tar.gz",
+ "md5_digest": "15ab75ef16b5c9164f8cf7dfbbd78ef8",
+ "downloads": 2159,
+ "filename": "luigi-1.0.5.tar.gz",
+ "packagetype": "sdist",
+ "path": "8c/16/4ac01f87ecb5f1cd1b083003cdaa485f1d4445817dd67fa4145d35243936/luigi-1.0.5.tar.gz",
+ "size": 225340
+ }
+ ],
+ "1.0.1": [
+ {
+ "has_sig": false,
+ "upload_time": "2013-04-23T00:07:42",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/ab/b3/47b0977818f72172e8385fa10775943e5e8546ff5b6a6867e9b048af1fbe/luigi-1.0.1.tar.gz",
+ "md5_digest": "884b7bd6b966ef4b00ec8a99d1cb5f98",
+ "downloads": 2280,
+ "filename": "luigi-1.0.1.tar.gz",
+ "packagetype": "sdist",
+ "path": "ab/b3/47b0977818f72172e8385fa10775943e5e8546ff5b6a6867e9b048af1fbe/luigi-1.0.1.tar.gz",
+ "size": 93270
+ }
+ ],
+ "2.0.1": [
+ {
+ "has_sig": false,
+ "upload_time": "2015-12-05T18:01:06",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/d4/2a/d6bff91d5ebb22449acb84b8212fd05d19e70713c16b092bfea4c2d2ce21/luigi-2.0.1.tar.gz",
+ "md5_digest": "625b7609fd6566fb14c25c8f2592d95f",
+ "downloads": 40965,
+ "filename": "luigi-2.0.1.tar.gz",
+ "packagetype": "sdist",
+ "path": "d4/2a/d6bff91d5ebb22449acb84b8212fd05d19e70713c16b092bfea4c2d2ce21/luigi-2.0.1.tar.gz",
+ "size": 1089311
+ }
+ ],
+ "2.0.0": [
+ {
+ "has_sig": false,
+ "upload_time": "2015-10-23T12:32:11",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/f6/b6/92a5de1c1d04e579183b97cc2aa1e9fabface3d096ebba5a28842b9db1bf/luigi-2.0.0.tar.gz",
+ "md5_digest": "06258afcfcdd2f829167450fd5fed604",
+ "downloads": 28712,
+ "filename": "luigi-2.0.0.tar.gz",
+ "packagetype": "sdist",
+ "path": "f6/b6/92a5de1c1d04e579183b97cc2aa1e9fabface3d096ebba5a28842b9db1bf/luigi-2.0.0.tar.gz",
+ "size": 1089886
+ }
+ ],
+ "1.0.8": [],
+ "1.0.9": [
+ {
+ "has_sig": false,
+ "upload_time": "2013-08-09T16:05:56",
+ "comment_text": "built for Darwin-11.4.2",
+ "python_version": "any",
+ "url": "https://pypi.org/packages/b4/76/0a96b93f10d6b1cbfec203c8b07fcfe67f209ac1c43f22572ff9e42fc8ca/luigi-1.0.9.macosx-10.7-intel.tar.gz",
+ "md5_digest": "c64aeabe850d1f6235ba353cc89f9174",
+ "downloads": 2115,
+ "filename": "luigi-1.0.9.macosx-10.7-intel.tar.gz",
+ "packagetype": "bdist_dumb",
+ "path": "b4/76/0a96b93f10d6b1cbfec203c8b07fcfe67f209ac1c43f22572ff9e42fc8ca/luigi-1.0.9.macosx-10.7-intel.tar.gz",
+ "size": 284105
+ },
+ {
+ "has_sig": false,
+ "upload_time": "2013-08-09T16:05:58",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/01/75/6fa1e73a8fda67c02da29189541be78577c8535ea7b721e4c5c3b62a7fcc/luigi-1.0.9.tar.gz",
+ "md5_digest": "024834d21a13276e84346fc000ff8cb4",
+ "downloads": 2156,
+ "filename": "luigi-1.0.9.tar.gz",
+ "packagetype": "sdist",
+ "path": "01/75/6fa1e73a8fda67c02da29189541be78577c8535ea7b721e4c5c3b62a7fcc/luigi-1.0.9.tar.gz",
+ "size": 228183
+ }
+ ],
+ "1.0.7": [
+ {
+ "has_sig": false,
+ "upload_time": "2013-08-08T00:03:23",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/2b/e1/551931e19ff0aa49489be78f471bfaaed6c5ae2da4b368c3fb4ccc3293ff/luigi-1.0.7.tar.gz",
+ "md5_digest": "38b4c984f1d3e702115a697d1637878c",
+ "downloads": 2184,
+ "filename": "luigi-1.0.7.tar.gz",
+ "packagetype": "sdist",
+ "path": "2b/e1/551931e19ff0aa49489be78f471bfaaed6c5ae2da4b368c3fb4ccc3293ff/luigi-1.0.7.tar.gz",
+ "size": 226592
+ }
+ ],
+ "2.2.0": [
+ {
+ "has_sig": false,
+ "upload_time": "2016-07-08T10:53:59",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/ab/f2/487cc0a14227f92d18291ea85bed2acbe09e23b717f42626af13f8a91fbe/luigi-2.2.0.tar.gz",
+ "md5_digest": "9e304df7d11dc54b5cc702ccd59f0012",
+ "downloads": 7715,
+ "filename": "luigi-2.2.0.tar.gz",
+ "packagetype": "sdist",
+ "path": "ab/f2/487cc0a14227f92d18291ea85bed2acbe09e23b717f42626af13f8a91fbe/luigi-2.2.0.tar.gz",
+ "size": 1098276
+ }
+ ],
+ "1.0": [
+ {
+ "has_sig": false,
+ "upload_time": "2012-10-21T18:51:38",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/fd/e9/cf3edb46c2be2d5f6e1cb345af929e5240473c310a1a004d42aa1c69e718/luigi-1.0.tar.gz",
+ "md5_digest": "eef9f05d7b9930943c6f631253a90cf6",
+ "downloads": 2664,
+ "filename": "luigi-1.0.tar.gz",
+ "packagetype": "sdist",
+ "path": "fd/e9/cf3edb46c2be2d5f6e1cb345af929e5240473c310a1a004d42aa1c69e718/luigi-1.0.tar.gz",
+ "size": 64636
+ }
+ ],
+ "2.1.0": [
+ {
+ "has_sig": false,
+ "upload_time": "2016-04-01T22:30:41",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/3b/e8/1935ca0d61e89c135b06e27ebeb39e819d73cd162f8b8fabb3cb62fe4852/luigi-2.1.0.tar.gz",
+ "md5_digest": "1f2b1e7de7a17d025163cff8d05f7a7a",
+ "downloads": 328,
+ "filename": "luigi-2.1.0.tar.gz",
+ "packagetype": "sdist",
+ "path": "3b/e8/1935ca0d61e89c135b06e27ebeb39e819d73cd162f8b8fabb3cb62fe4852/luigi-2.1.0.tar.gz",
+ "size": 1122512
+ }
+ ],
+ "2.1.1": [
+ {
+ "has_sig": false,
+ "upload_time": "2016-04-06T07:17:35",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/47/ef/50c8d8b71b6613bb17088cf7b02319dd907d8bd05f6280e27a4199c68402/luigi-2.1.1.tar.gz",
+ "md5_digest": "f05aab98f4212d807b5ab348239058ec",
+ "downloads": 24120,
+ "filename": "luigi-2.1.1.tar.gz",
+ "packagetype": "sdist",
+ "path": "47/ef/50c8d8b71b6613bb17088cf7b02319dd907d8bd05f6280e27a4199c68402/luigi-2.1.1.tar.gz",
+ "size": 1129059
+ }
+ ],
+ "1.0.2": [
+ {
+ "has_sig": false,
+ "upload_time": "2013-04-25T17:18:57",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/9a/d5/6351a5b71f2bb6501211f6fc3d5e102d72017ef289b6729610208765617f/luigi-1.0.2.tar.gz",
+ "md5_digest": "9ef8a6a5783f0bd5dbdbe4b8a889bb84",
+ "downloads": 2215,
+ "filename": "luigi-1.0.2.tar.gz",
+ "packagetype": "sdist",
+ "path": "9a/d5/6351a5b71f2bb6501211f6fc3d5e102d72017ef289b6729610208765617f/luigi-1.0.2.tar.gz",
+ "size": 78573
+ }
+ ],
+ "1.0.3": [
+ {
+ "has_sig": false,
+ "upload_time": "2013-04-25T17:20:20",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/d6/8a/d9bd49a8ce0cb8e5e26f35436e5dafab01bb4fb13d7189a59f95b52a8a7b/luigi-1.0.3.tar.gz",
+ "md5_digest": "8fb2043ccf28c6034c3b2e1c8b0a92ff",
+ "downloads": 10655,
+ "filename": "luigi-1.0.3.tar.gz",
+ "packagetype": "sdist",
+ "path": "d6/8a/d9bd49a8ce0cb8e5e26f35436e5dafab01bb4fb13d7189a59f95b52a8a7b/luigi-1.0.3.tar.gz",
+ "size": 93196
+ }
+ ],
+ "1.0.16": [
+ {
+ "has_sig": false,
+ "upload_time": "2014-05-17T16:34:18",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/be/43/d9c21e162f3412833ab57d8fb22e328dbfec9e68e562e09e612f8bb8afd0/luigi-1.0.16.tar.gz",
+ "md5_digest": "edbebf80d6c332fcd07907c14da4d326",
+ "downloads": 30433,
+ "filename": "luigi-1.0.16.tar.gz",
+ "packagetype": "sdist",
+ "path": "be/43/d9c21e162f3412833ab57d8fb22e328dbfec9e68e562e09e612f8bb8afd0/luigi-1.0.16.tar.gz",
+ "size": 277787
+ }
+ ],
+ "1.0.17": [
+ {
+ "has_sig": false,
+ "upload_time": "2014-08-26T14:32:35",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/ba/f5/b3d877f760ae4cd741ba90ca4b0fcf0527b1e7e72ec34d13a8762afbdbc0/luigi-1.0.17.tar.gz",
+ "md5_digest": "13151df79c743df21358560f0e7e9321",
+ "downloads": 3871,
+ "filename": "luigi-1.0.17.tar.gz",
+ "packagetype": "sdist",
+ "path": "ba/f5/b3d877f760ae4cd741ba90ca4b0fcf0527b1e7e72ec34d13a8762afbdbc0/luigi-1.0.17.tar.gz",
+ "size": 296199
+ }
+ ],
+ "1.0.14": [
+ {
+ "has_sig": false,
+ "upload_time": "2014-05-14T11:56:59",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/31/7a/697567f198c3187d329bd5239380595c18b1d4cec2100abb8683a5431449/luigi-1.0.14.tar.gz",
+ "md5_digest": "f9212f6cd1dc046739664b5bedcc3415",
+ "downloads": 1802,
+ "filename": "luigi-1.0.14.tar.gz",
+ "packagetype": "sdist",
+ "path": "31/7a/697567f198c3187d329bd5239380595c18b1d4cec2100abb8683a5431449/luigi-1.0.14.tar.gz",
+ "size": 277355
+ }
+ ],
+ "1.0.15": [
+ {
+ "has_sig": false,
+ "upload_time": "2014-05-14T14:18:30",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/e9/a4/229f2ba9f070bb167249989c872b1e6bd84afcaba5aa14d16f913e2a3388/luigi-1.0.15.tar.gz",
+ "md5_digest": "7222e00a048b66d6e92af253fc86810b",
+ "downloads": 1949,
+ "filename": "luigi-1.0.15.tar.gz",
+ "packagetype": "sdist",
+ "path": "e9/a4/229f2ba9f070bb167249989c872b1e6bd84afcaba5aa14d16f913e2a3388/luigi-1.0.15.tar.gz",
+ "size": 277722
+ }
+ ],
+ "1.0.12": [
+ {
+ "has_sig": false,
+ "upload_time": "2013-11-26T04:18:10",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/5a/09/38185b73e7ea6d477ea01cc85f075b77730595b1f8b0e55a4edbeac66d53/luigi-1.0.12.tar.gz",
+ "md5_digest": "58d33b2f940bd4ad2baa5281d4240345",
+ "downloads": 18087,
+ "filename": "luigi-1.0.12.tar.gz",
+ "packagetype": "sdist",
+ "path": "5a/09/38185b73e7ea6d477ea01cc85f075b77730595b1f8b0e55a4edbeac66d53/luigi-1.0.12.tar.gz",
+ "size": 238722
+ }
+ ],
+ "1.0.13": [
+ {
+ "has_sig": false,
+ "upload_time": "2014-02-03T05:44:54",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/bb/d8/ec43a5bbbf963675a198dd0c050f61df859c326b9373d26ac22bee00aa95/luigi-1.0.13.tar.gz",
+ "md5_digest": "3150d20f66026df00887625f11720acb",
+ "downloads": 5096,
+ "filename": "luigi-1.0.13.tar.gz",
+ "packagetype": "sdist",
+ "path": "bb/d8/ec43a5bbbf963675a198dd0c050f61df859c326b9373d26ac22bee00aa95/luigi-1.0.13.tar.gz",
+ "size": 293454
+ }
+ ],
+ "1.0.10": [
+ {
+ "has_sig": false,
+ "upload_time": "2013-08-09T16:06:37",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/07/c1/26b984d5f1084e57ff9207a9b1873ce0a0c3d4c1c857f20fa38e93c45b3b/luigi-1.0.10.tar.gz",
+ "md5_digest": "7f6a390a7d928f3866f13bd5be55a91d",
+ "downloads": 4379,
+ "filename": "luigi-1.0.10.tar.gz",
+ "packagetype": "sdist",
+ "path": "07/c1/26b984d5f1084e57ff9207a9b1873ce0a0c3d4c1c857f20fa38e93c45b3b/luigi-1.0.10.tar.gz",
+ "size": 228201
+ }
+ ],
+ "1.0.11": [
+ {
+ "has_sig": false,
+ "upload_time": "2013-11-21T23:07:21",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/bd/f4/8828fbced3792398065560a5d7203df45b85199f230bde9364d9ce37726e/luigi-1.0.11.tar.gz",
+ "md5_digest": "d5858aeeb5deef91ae819376ebefd83d",
+ "downloads": 2062,
+ "filename": "luigi-1.0.11.tar.gz",
+ "packagetype": "sdist",
+ "path": "bd/f4/8828fbced3792398065560a5d7203df45b85199f230bde9364d9ce37726e/luigi-1.0.11.tar.gz",
+ "size": 238741
+ }
+ ],
+ "1.0.18": [
+ {
+ "has_sig": false,
+ "upload_time": "2014-09-15T11:40:39",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/0b/9a/f51f96ca7ee9a330d6912d08c5fe237008de1c10c52114722f68d15bdee8/luigi-1.0.18.tar.gz",
+ "md5_digest": "e7cda3de5128d697ecb89b126522aa21",
+ "downloads": 2150,
+ "filename": "luigi-1.0.18.tar.gz",
+ "packagetype": "sdist",
+ "path": "0b/9a/f51f96ca7ee9a330d6912d08c5fe237008de1c10c52114722f68d15bdee8/luigi-1.0.18.tar.gz",
+ "size": 297983
+ }
+ ],
+ "1.0.19": [
+ {
+ "has_sig": false,
+ "upload_time": "2014-09-22T12:14:38",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/f5/a2/ee698ff0e301b321ffccf0a254df5e30e5ab734d23886606937f73b5ccb6/luigi-1.0.19.tar.gz",
+ "md5_digest": "3170554e32a7a630f9457d3298741538",
+ "downloads": 207006,
+ "filename": "luigi-1.0.19.tar.gz",
+ "packagetype": "sdist",
+ "path": "f5/a2/ee698ff0e301b321ffccf0a254df5e30e5ab734d23886606937f73b5ccb6/luigi-1.0.19.tar.gz",
+ "size": 300167
+ }
+ ],
+ "2.3.0": [
+ {
+ "has_sig": false,
+ "upload_time": "2016-08-12T03:20:41",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/25/64/5383d94b5b44e9c1443c1a6b857210ace8205954359f8353a50c16deb664/luigi-2.3.0.tar.gz",
+ "md5_digest": "3b7e0b4c8d684a168c97a4fb2d9340ca",
+ "downloads": 1188,
+ "filename": "luigi-2.3.0.tar.gz",
+ "packagetype": "sdist",
+ "path": "25/64/5383d94b5b44e9c1443c1a6b857210ace8205954359f8353a50c16deb664/luigi-2.3.0.tar.gz",
+ "size": 1113879
+ }
+ ],
+ "2.3.1": [
+ {
+ "has_sig": false,
+ "upload_time": "2016-08-25T02:41:26",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/55/8d/0842fbdb05a18d4a9e578f7c1661fbc719c625b1d1f0f9ceb08ea8bea518/luigi-2.3.1.tar.gz",
+ "md5_digest": "e48786e9ac71d8fd58694529d3f5539d",
+ "downloads": 7557,
+ "filename": "luigi-2.3.1.tar.gz",
+ "packagetype": "sdist",
+ "path": "55/8d/0842fbdb05a18d4a9e578f7c1661fbc719c625b1d1f0f9ceb08ea8bea518/luigi-2.3.1.tar.gz",
+ "size": 1114644
+ }
+ ],
+ "2.3.2": [
+ {
+ "has_sig": false,
+ "upload_time": "2016-09-20T09:46:25",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/d5/0b/531d2efe721a7195bd593ff2d92d41720b10dae0093f9abfd2c073560dcf/luigi-2.3.2.tar.gz",
+ "md5_digest": "cd622f6fbae981bc1b8f9b0132b189b8",
+ "downloads": 8558,
+ "filename": "luigi-2.3.2.tar.gz",
+ "packagetype": "sdist",
+ "path": "d5/0b/531d2efe721a7195bd593ff2d92d41720b10dae0093f9abfd2c073560dcf/luigi-2.3.2.tar.gz",
+ "size": 1116310
+ }
+ ],
+ "2.3.3": [
+ {
+ "has_sig": false,
+ "upload_time": "2016-10-21T04:04:56",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/80/83/f1f805266ba83964b90e31890d8f8f9ee4b82c40e9778fac350bdf830fba/luigi-2.3.3.tar.gz",
+ "md5_digest": "dea3b1cb636f7ac141c6054717728830",
+ "downloads": 7910,
+ "filename": "luigi-2.3.3.tar.gz",
+ "packagetype": "sdist",
+ "path": "80/83/f1f805266ba83964b90e31890d8f8f9ee4b82c40e9778fac350bdf830fba/luigi-2.3.3.tar.gz",
+ "size": 1119561
+ }
+ ],
+ "1.3.0": [
+ {
+ "has_sig": false,
+ "upload_time": "2015-06-26T13:19:38",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/7a/3d/da7ebf732a295098ec7b72aefd6580cc68dad461fdbce9265ddb8a3544f8/luigi-1.3.0.tar.gz",
+ "md5_digest": "948a6574e4d4e1d1d8b8a355ca0cdaf7",
+ "downloads": 44182,
+ "filename": "luigi-1.3.0.tar.gz",
+ "packagetype": "sdist",
+ "path": "7a/3d/da7ebf732a295098ec7b72aefd6580cc68dad461fdbce9265ddb8a3544f8/luigi-1.3.0.tar.gz",
+ "size": 457934
+ }
+ ],
+ "1.2.1": [
+ {
+ "has_sig": false,
+ "upload_time": "2015-05-26T10:00:32",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/3f/c7/7f5e1f5016a23c6cf2b3152bd27d994ad3b384e59e3c1bfdec444669853d/luigi-1.2.1.tar.gz",
+ "md5_digest": "a147bba0bb1999b5856f4910bf15a9c0",
+ "downloads": 25856,
+ "filename": "luigi-1.2.1.tar.gz",
+ "packagetype": "sdist",
+ "path": "3f/c7/7f5e1f5016a23c6cf2b3152bd27d994ad3b384e59e3c1bfdec444669853d/luigi-1.2.1.tar.gz",
+ "size": 449107
+ }
+ ],
+ "2.4.0": [
+ {
+ "has_sig": false,
+ "upload_time": "2016-12-02T04:52:12",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/6a/84/42bea7839bc6eee8c219775f6afe3e296a554985a0aa216fb6090478a3e5/luigi-2.4.0.tar.gz",
+ "md5_digest": "76303fa7281ac0c6a95aa9ada13acc3e",
+ "downloads": 5965,
+ "filename": "luigi-2.4.0.tar.gz",
+ "packagetype": "sdist",
+ "path": "6a/84/42bea7839bc6eee8c219775f6afe3e296a554985a0aa216fb6090478a3e5/luigi-2.4.0.tar.gz",
+ "size": 1128461
+ }
+ ],
+ "2.5.0": [
+ {
+ "has_sig": false,
+ "upload_time": "2017-01-10T07:54:38",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/9a/f2/7f7bf85e1e380375cc8a291ed648c733b4f310fe43a00073fff12bb61692/luigi-2.5.0.tar.gz",
+ "md5_digest": "26c29cd4d18381b1f148a7a43cbee335",
+ "downloads": 0,
+ "filename": "luigi-2.5.0.tar.gz",
+ "packagetype": "sdist",
+ "path": "9a/f2/7f7bf85e1e380375cc8a291ed648c733b4f310fe43a00073fff12bb61692/luigi-2.5.0.tar.gz",
+ "size": 1130701
+ }
+ ],
+ "1.0.4": [
+ {
+ "has_sig": false,
+ "upload_time": "2013-08-07T18:46:38",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/56/09/d3776490559b62d53b7cf87cb066b76b9a7f91d6749325d146c76a2adc42/luigi-1.0.4.tar.gz",
+ "md5_digest": "d5eef08fb8f76875bc28680ec72511f8",
+ "downloads": 2175,
+ "filename": "luigi-1.0.4.tar.gz",
+ "packagetype": "sdist",
+ "path": "56/09/d3776490559b62d53b7cf87cb066b76b9a7f91d6749325d146c76a2adc42/luigi-1.0.4.tar.gz",
+ "size": 71168
+ }
+ ],
+ "2.6.0": [
+ {
+ "has_sig": false,
+ "upload_time": "2017-02-10T06:57:18",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/9f/aa/5067601c565d61c8e1f172035eee4f1d50f25a193b9041f17ebc6fff5764/luigi-2.6.0.tar.gz",
+ "md5_digest": "8c36cf3d37525ccc57f6ecc24431bdef",
+ "downloads": 0,
+ "filename": "luigi-2.6.0.tar.gz",
+ "packagetype": "sdist",
+ "path": "9f/aa/5067601c565d61c8e1f172035eee4f1d50f25a193b9041f17ebc6fff5764/luigi-2.6.0.tar.gz",
+ "size": 1158747
+ }
+ ],
+ "1.0.24": [
+ {
+ "has_sig": false,
+ "upload_time": "2015-02-11T12:01:07",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/3c/a5/3bc272eb6317147ddaf8c0c3bf7ba47a684216f5e16c4fdf80f05ac94d60/luigi-1.0.24.tar.gz",
+ "md5_digest": "44c6f413dff37e6cd295e696f2cdea19",
+ "downloads": 23418,
+ "filename": "luigi-1.0.24.tar.gz",
+ "packagetype": "sdist",
+ "path": "3c/a5/3bc272eb6317147ddaf8c0c3bf7ba47a684216f5e16c4fdf80f05ac94d60/luigi-1.0.24.tar.gz",
+ "size": 333339
+ }
+ ],
+ "1.0.23": [
+ {
+ "has_sig": false,
+ "upload_time": "2015-02-10T11:53:49",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/2e/5c/d53458d78415079fef6bc2231f7b5f5e5876e90f39cc2c57a054379df0cc/luigi-1.0.23.tar.gz",
+ "md5_digest": "0c9d7dd091b913f9076b5517dc41cd91",
+ "downloads": 2542,
+ "filename": "luigi-1.0.23.tar.gz",
+ "packagetype": "sdist",
+ "path": "2e/5c/d53458d78415079fef6bc2231f7b5f5e5876e90f39cc2c57a054379df0cc/luigi-1.0.23.tar.gz",
+ "size": 333182
+ }
+ ],
+ "1.0.22": [
+ {
+ "has_sig": false,
+ "upload_time": "2015-02-10T04:20:16",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/b7/8b/d7751ae52e30e1b872bcaaf4626b202e0fc61c2c91fef91912b6e901545e/luigi-1.0.22.tar.gz",
+ "md5_digest": "10762c7d1999babdb38471a26b1d2880",
+ "downloads": 1072,
+ "filename": "luigi-1.0.22.tar.gz",
+ "packagetype": "sdist",
+ "path": "b7/8b/d7751ae52e30e1b872bcaaf4626b202e0fc61c2c91fef91912b6e901545e/luigi-1.0.22.tar.gz",
+ "size": 333175
+ }
+ ],
+ "1.0.21": [],
+ "1.0.20": [
+ {
+ "has_sig": false,
+ "upload_time": "2015-01-21T16:27:35",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/2b/88/804830f0c78ebe1a2b1dfbf723bfcd97f6822f4e139da5909cd87baf2374/luigi-1.0.20.tar.gz",
+ "md5_digest": "f1edc408bb19ffaf18a88693abc0d765",
+ "downloads": 6245,
+ "filename": "luigi-1.0.20.tar.gz",
+ "packagetype": "sdist",
+ "path": "2b/88/804830f0c78ebe1a2b1dfbf723bfcd97f6822f4e139da5909cd87baf2374/luigi-1.0.20.tar.gz",
+ "size": 324700
+ }
+ ]
+ },
+ "urls": [
+ {
+ "has_sig": false,
+ "upload_time": "2017-02-10T06:57:18",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/9f/aa/5067601c565d61c8e1f172035eee4f1d50f25a193b9041f17ebc6fff5764/luigi-2.6.0.tar.gz",
+ "md5_digest": "8c36cf3d37525ccc57f6ecc24431bdef",
+ "downloads": 0,
+ "filename": "luigi-2.6.0.tar.gz",
+ "packagetype": "sdist",
+ "path": "9f/aa/5067601c565d61c8e1f172035eee4f1d50f25a193b9041f17ebc6fff5764/luigi-2.6.0.tar.gz",
+ "size": 1158747
+ }
+ ]
+}
diff --git a/uv/spec/fixtures/pypi/pypi_response_bitbucket.json b/uv/spec/fixtures/pypi/pypi_response_bitbucket.json
new file mode 100644
index 00000000000..76f418490dc
--- /dev/null
+++ b/uv/spec/fixtures/pypi/pypi_response_bitbucket.json
@@ -0,0 +1,677 @@
+{
+ "info": {
+ "maintainer": "",
+ "docs_url": null,
+ "requires_python": "",
+ "maintainer_email": "",
+ "cheesecake_code_kwalitee_id": null,
+ "keywords": "",
+ "package_url": "http://pypi.org/pypi/luigi",
+ "author": "The Luigi Authors",
+ "author_email": "",
+ "download_url": "",
+ "platform": "",
+ "version": "2.6.0",
+ "cheesecake_documentation_id": null,
+ "_pypi_hidden": false,
+ "description": ".. note::\n\n For the latest source, discussion, etc, please visit the\n `GitHub repository `_\n\n\n.. figure:: https://raw.githubusercontent.com/spotify/luigi/master/doc/luigi.png\n :alt: Luigi Logo\n :align: center\n\n.. image:: https://img.shields.io/travis/spotify/luigi/master.svg?style=flat\n :target: https://travis-ci.org/spotify/luigi\n\n.. image:: https://img.shields.io/codecov/c/github/spotify/luigi/master.svg?style=flat\n :target: https://codecov.io/gh/spotify/luigi?branch=master\n\n.. image:: https://landscape.io/github/spotify/luigi/master/landscape.svg?style=flat\n :target: https://landscape.io/github/spotify/luigi/master\n\n.. image:: https://img.shields.io/pypi/v/luigi.svg?style=flat\n :target: https://pypi.org/pypi/luigi\n\n.. image:: https://img.shields.io/pypi/l/luigi.svg?style=flat\n :target: https://pypi.org/pypi/luigi\n\nLuigi is a Python (2.7, 3.3, 3.4, 3.5) package that helps you build complex pipelines of batch\njobs. It handles dependency resolution, workflow management, visualization,\nhandling failures, command line integration, and much more.\n\nGetting Started\n---------------\n\nRun ``pip install luigi`` to install the latest stable version from `PyPI\n`_. Documentation for the latest release is\nhosted `here `__.\n\nFor the bleeding edge code, ``pip install\ngit+https://bitbucket.org/spotify/luigi.git``. Bleeding edge documentation can be\nfound `here `__.\n\nBackground\n----------\n\nThe purpose of Luigi is to address all the plumbing typically associated\nwith long-running batch processes. You want to chain many tasks,\nautomate them, and failures *will* happen. These tasks can be anything,\nbut are typically long running things like\n`Hadoop `_ jobs, dumping data to/from\ndatabases, running machine learning algorithms, or anything else.\n\nThere are other software packages that focus on lower level aspects of\ndata processing, like `Hive `__,\n`Pig `_, or\n`Cascading `_. Luigi is not a framework to\nreplace these. Instead it helps you stitch many tasks together, where\neach task can be a `Hive query `__,\na `Hadoop job in Java `_,\na `Spark job in Scala or Python `_\na Python snippet,\n`dumping a table `_\nfrom a database, or anything else. It's easy to build up\nlong-running pipelines that comprise thousands of tasks and take days or\nweeks to complete. Luigi takes care of a lot of the workflow management\nso that you can focus on the tasks themselves and their dependencies.\n\nYou can build pretty much any task you want, but Luigi also comes with a\n*toolbox* of several common task templates that you use. It includes\nsupport for running\n`Python mapreduce jobs `_\nin Hadoop, as well as\n`Hive `__,\nand `Pig `__,\njobs. It also comes with\n`file system abstractions for HDFS `_,\nand local files that ensures all file system operations are atomic. This\nis important because it means your data pipeline will not crash in a\nstate containing partial data.\n\nVisualiser page\n---------------\n\nThe Luigi server comes with a web interface too, so you can search and filter\namong all your tasks.\n\n.. figure:: https://raw.githubusercontent.com/spotify/luigi/master/doc/visualiser_front_page.png\n :alt: Visualiser page\n\nDependency graph example\n------------------------\n\nJust to give you an idea of what Luigi does, this is a screen shot from\nsomething we are running in production. Using Luigi's visualiser, we get\na nice visual overview of the dependency graph of the workflow. Each\nnode represents a task which has to be run. Green tasks are already\ncompleted whereas yellow tasks are yet to be run. Most of these tasks\nare Hadoop jobs, but there are also some things that run locally and\nbuild up data files.\n\n.. figure:: https://raw.githubusercontent.com/spotify/luigi/master/doc/user_recs.png\n :alt: Dependency graph\n\nPhilosophy\n----------\n\nConceptually, Luigi is similar to `GNU\nMake `_ where you have certain tasks\nand these tasks in turn may have dependencies on other tasks. There are\nalso some similarities to `Oozie `_\nand `Azkaban `_. One major\ndifference is that Luigi is not just built specifically for Hadoop, and\nit's easy to extend it with other kinds of tasks.\n\nEverything in Luigi is in Python. Instead of XML configuration or\nsimilar external data files, the dependency graph is specified *within\nPython*. This makes it easy to build up complex dependency graphs of\ntasks, where the dependencies can involve date algebra or recursive\nreferences to other versions of the same task. However, the workflow can\ntrigger things not in Python, such as running\n`Pig scripts `_\nor `scp'ing files `_.\n\nWho uses Luigi?\n---------------\n\nWe use Luigi internally at `Spotify `_ to run\nthousands of tasks every day, organized in complex dependency graphs.\nMost of these tasks are Hadoop jobs. Luigi provides an infrastructure\nthat powers all kinds of stuff including recommendations, toplists, A/B\ntest analysis, external reports, internal dashboards, etc.\n\nSince Luigi is open source and without any registration walls, the exact number\nof Luigi users is unknown. But based on the number of unique contributors, we\nexpect hundreds of enterprises to use it. Some users have written blog posts\nor held presentations about Luigi:\n\n* `Spotify (NYC Data Science) `_\n* `Foursquare `_\n* `Mortar Data `_\n* `Stripe `_\n* `Asana `_\n* `Buffer `_\n* `SeatGeek `_\n* `Treasure Data `_\n* `Growth Intelligence `_\n* `AdRoll `_\n* `Schibsted `_\n* `17zuoye `_\n* `enbrite.ly `_\n* `Dow Jones / The Wall Street Journal `_\n* `Hotels.com `_\n* `Custobar (Metrics Monday Helsinki) `_\n* `Blendle `_\n* `TrustYou (PyData Berlin 2015) `_\n* `Groupon / OrderUp `_\n\nWe're more than happy to have your company added here. Just send a PR on GitHub.\n\nExternal links\n--------------\n\n* `Mailing List `_ for discussions and asking questions. (Google Groups)\n* `Releases `_ (PyPI)\n* `Source code `_ (Github)\n* `Hubot Integration `_ plugin for Slack, Hipchat, etc (Github)\n\nAuthors\n-------\n\nLuigi was built at `Spotify `_, mainly by\n`Erik Bernhardsson `_ and\n`Elias Freider `_.\n`Many other people `_\nhave contributed since open sourcing in late 2012.\n`Arash Rouhani `_ is currently the chief\nmaintainer of Luigi.\n",
+ "release_url": "http://pypi.org/pypi/luigi/2.6.0",
+ "downloads": {
+ "last_month": 0,
+ "last_week": 0,
+ "last_day": 0
+ },
+ "_pypi_ordering": 41,
+ "classifiers": [
+ "Development Status :: 5 - Production/Stable",
+ "Environment :: Console",
+ "Environment :: Web Environment",
+ "Intended Audience :: Developers",
+ "Intended Audience :: System Administrators",
+ "License :: OSI Approved :: Apache Software License",
+ "Programming Language :: Python :: 2.7",
+ "Programming Language :: Python :: 3.3",
+ "Programming Language :: Python :: 3.4",
+ "Programming Language :: Python :: 3.5",
+ "Topic :: System :: Monitoring"
+ ],
+ "bugtrack_url": null,
+ "name": "luigi",
+ "license": "Apache License 2.0",
+ "summary": "Workflow mgmgt + task scheduling + dependency resolution",
+ "home_page": "https://bitbucket.org/spotify/luigi",
+ "cheesecake_installability_id": null
+ },
+ "releases": {
+ "1.1.1": [
+ {
+ "has_sig": false,
+ "upload_time": "2015-03-16T13:02:09",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/59/d2/5f32dc62bfa1b430cb902bcd26c652f9fe4c9462a3b06bc1ca6e80127d85/luigi-1.1.1.tar.gz",
+ "md5_digest": "5659011287f08ff6f1a36f9b9ab04269",
+ "downloads": 2776,
+ "filename": "luigi-1.1.1.tar.gz",
+ "packagetype": "sdist",
+ "path": "59/d2/5f32dc62bfa1b430cb902bcd26c652f9fe4c9462a3b06bc1ca6e80127d85/luigi-1.1.1.tar.gz",
+ "size": 357235
+ }
+ ],
+ "1.1.0": [
+ {
+ "has_sig": false,
+ "upload_time": "2015-03-07T17:29:44",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/85/b8/7a89ec0981570ae1fd30f102c8410381770db7898bbfdea3e1aa3ddd3b43/luigi-1.1.0.tar.gz",
+ "md5_digest": "742e9d7acbdceb007c5280b9e9f0f00d",
+ "downloads": 2713,
+ "filename": "luigi-1.1.0.tar.gz",
+ "packagetype": "sdist",
+ "path": "85/b8/7a89ec0981570ae1fd30f102c8410381770db7898bbfdea3e1aa3ddd3b43/luigi-1.1.0.tar.gz",
+ "size": 349728
+ }
+ ],
+ "1.0.6": [
+ {
+ "has_sig": false,
+ "upload_time": "2013-08-07T23:47:21",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/e9/3d/68c6ca27f4bda9aabfef3c58c2866cf5db6e05524162d36b3adb4e8fa8e5/luigi-1.0.6.tar.gz",
+ "md5_digest": "173f1868d0f8c318b2f9e91036d9bff2",
+ "downloads": 2153,
+ "filename": "luigi-1.0.6.tar.gz",
+ "packagetype": "sdist",
+ "path": "e9/3d/68c6ca27f4bda9aabfef3c58c2866cf5db6e05524162d36b3adb4e8fa8e5/luigi-1.0.6.tar.gz",
+ "size": 225527
+ }
+ ],
+ "1.1.2": [
+ {
+ "has_sig": false,
+ "upload_time": "2015-03-18T00:50:52",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/3d/26/191da8144fd2a881f72c6d87df68ee654e684989dcaa3559dcbc9c0a6355/luigi-1.1.2.tar.gz",
+ "md5_digest": "a617f82f1354c49cb227b7877d3defa2",
+ "downloads": 44221,
+ "filename": "luigi-1.1.2.tar.gz",
+ "packagetype": "sdist",
+ "path": "3d/26/191da8144fd2a881f72c6d87df68ee654e684989dcaa3559dcbc9c0a6355/luigi-1.1.2.tar.gz",
+ "size": 357305
+ }
+ ],
+ "1.0.5": [
+ {
+ "has_sig": false,
+ "upload_time": "2013-08-07T23:44:22",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/8c/16/4ac01f87ecb5f1cd1b083003cdaa485f1d4445817dd67fa4145d35243936/luigi-1.0.5.tar.gz",
+ "md5_digest": "15ab75ef16b5c9164f8cf7dfbbd78ef8",
+ "downloads": 2159,
+ "filename": "luigi-1.0.5.tar.gz",
+ "packagetype": "sdist",
+ "path": "8c/16/4ac01f87ecb5f1cd1b083003cdaa485f1d4445817dd67fa4145d35243936/luigi-1.0.5.tar.gz",
+ "size": 225340
+ }
+ ],
+ "1.0.1": [
+ {
+ "has_sig": false,
+ "upload_time": "2013-04-23T00:07:42",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/ab/b3/47b0977818f72172e8385fa10775943e5e8546ff5b6a6867e9b048af1fbe/luigi-1.0.1.tar.gz",
+ "md5_digest": "884b7bd6b966ef4b00ec8a99d1cb5f98",
+ "downloads": 2280,
+ "filename": "luigi-1.0.1.tar.gz",
+ "packagetype": "sdist",
+ "path": "ab/b3/47b0977818f72172e8385fa10775943e5e8546ff5b6a6867e9b048af1fbe/luigi-1.0.1.tar.gz",
+ "size": 93270
+ }
+ ],
+ "2.0.1": [
+ {
+ "has_sig": false,
+ "upload_time": "2015-12-05T18:01:06",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/d4/2a/d6bff91d5ebb22449acb84b8212fd05d19e70713c16b092bfea4c2d2ce21/luigi-2.0.1.tar.gz",
+ "md5_digest": "625b7609fd6566fb14c25c8f2592d95f",
+ "downloads": 40965,
+ "filename": "luigi-2.0.1.tar.gz",
+ "packagetype": "sdist",
+ "path": "d4/2a/d6bff91d5ebb22449acb84b8212fd05d19e70713c16b092bfea4c2d2ce21/luigi-2.0.1.tar.gz",
+ "size": 1089311
+ }
+ ],
+ "2.0.0": [
+ {
+ "has_sig": false,
+ "upload_time": "2015-10-23T12:32:11",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/f6/b6/92a5de1c1d04e579183b97cc2aa1e9fabface3d096ebba5a28842b9db1bf/luigi-2.0.0.tar.gz",
+ "md5_digest": "06258afcfcdd2f829167450fd5fed604",
+ "downloads": 28712,
+ "filename": "luigi-2.0.0.tar.gz",
+ "packagetype": "sdist",
+ "path": "f6/b6/92a5de1c1d04e579183b97cc2aa1e9fabface3d096ebba5a28842b9db1bf/luigi-2.0.0.tar.gz",
+ "size": 1089886
+ }
+ ],
+ "1.0.8": [],
+ "1.0.9": [
+ {
+ "has_sig": false,
+ "upload_time": "2013-08-09T16:05:56",
+ "comment_text": "built for Darwin-11.4.2",
+ "python_version": "any",
+ "url": "https://pypi.org/packages/b4/76/0a96b93f10d6b1cbfec203c8b07fcfe67f209ac1c43f22572ff9e42fc8ca/luigi-1.0.9.macosx-10.7-intel.tar.gz",
+ "md5_digest": "c64aeabe850d1f6235ba353cc89f9174",
+ "downloads": 2115,
+ "filename": "luigi-1.0.9.macosx-10.7-intel.tar.gz",
+ "packagetype": "bdist_dumb",
+ "path": "b4/76/0a96b93f10d6b1cbfec203c8b07fcfe67f209ac1c43f22572ff9e42fc8ca/luigi-1.0.9.macosx-10.7-intel.tar.gz",
+ "size": 284105
+ },
+ {
+ "has_sig": false,
+ "upload_time": "2013-08-09T16:05:58",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/01/75/6fa1e73a8fda67c02da29189541be78577c8535ea7b721e4c5c3b62a7fcc/luigi-1.0.9.tar.gz",
+ "md5_digest": "024834d21a13276e84346fc000ff8cb4",
+ "downloads": 2156,
+ "filename": "luigi-1.0.9.tar.gz",
+ "packagetype": "sdist",
+ "path": "01/75/6fa1e73a8fda67c02da29189541be78577c8535ea7b721e4c5c3b62a7fcc/luigi-1.0.9.tar.gz",
+ "size": 228183
+ }
+ ],
+ "1.0.7": [
+ {
+ "has_sig": false,
+ "upload_time": "2013-08-08T00:03:23",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/2b/e1/551931e19ff0aa49489be78f471bfaaed6c5ae2da4b368c3fb4ccc3293ff/luigi-1.0.7.tar.gz",
+ "md5_digest": "38b4c984f1d3e702115a697d1637878c",
+ "downloads": 2184,
+ "filename": "luigi-1.0.7.tar.gz",
+ "packagetype": "sdist",
+ "path": "2b/e1/551931e19ff0aa49489be78f471bfaaed6c5ae2da4b368c3fb4ccc3293ff/luigi-1.0.7.tar.gz",
+ "size": 226592
+ }
+ ],
+ "2.2.0": [
+ {
+ "has_sig": false,
+ "upload_time": "2016-07-08T10:53:59",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/ab/f2/487cc0a14227f92d18291ea85bed2acbe09e23b717f42626af13f8a91fbe/luigi-2.2.0.tar.gz",
+ "md5_digest": "9e304df7d11dc54b5cc702ccd59f0012",
+ "downloads": 7715,
+ "filename": "luigi-2.2.0.tar.gz",
+ "packagetype": "sdist",
+ "path": "ab/f2/487cc0a14227f92d18291ea85bed2acbe09e23b717f42626af13f8a91fbe/luigi-2.2.0.tar.gz",
+ "size": 1098276
+ }
+ ],
+ "1.0": [
+ {
+ "has_sig": false,
+ "upload_time": "2012-10-21T18:51:38",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/fd/e9/cf3edb46c2be2d5f6e1cb345af929e5240473c310a1a004d42aa1c69e718/luigi-1.0.tar.gz",
+ "md5_digest": "eef9f05d7b9930943c6f631253a90cf6",
+ "downloads": 2664,
+ "filename": "luigi-1.0.tar.gz",
+ "packagetype": "sdist",
+ "path": "fd/e9/cf3edb46c2be2d5f6e1cb345af929e5240473c310a1a004d42aa1c69e718/luigi-1.0.tar.gz",
+ "size": 64636
+ }
+ ],
+ "2.1.0": [
+ {
+ "has_sig": false,
+ "upload_time": "2016-04-01T22:30:41",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/3b/e8/1935ca0d61e89c135b06e27ebeb39e819d73cd162f8b8fabb3cb62fe4852/luigi-2.1.0.tar.gz",
+ "md5_digest": "1f2b1e7de7a17d025163cff8d05f7a7a",
+ "downloads": 328,
+ "filename": "luigi-2.1.0.tar.gz",
+ "packagetype": "sdist",
+ "path": "3b/e8/1935ca0d61e89c135b06e27ebeb39e819d73cd162f8b8fabb3cb62fe4852/luigi-2.1.0.tar.gz",
+ "size": 1122512
+ }
+ ],
+ "2.1.1": [
+ {
+ "has_sig": false,
+ "upload_time": "2016-04-06T07:17:35",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/47/ef/50c8d8b71b6613bb17088cf7b02319dd907d8bd05f6280e27a4199c68402/luigi-2.1.1.tar.gz",
+ "md5_digest": "f05aab98f4212d807b5ab348239058ec",
+ "downloads": 24120,
+ "filename": "luigi-2.1.1.tar.gz",
+ "packagetype": "sdist",
+ "path": "47/ef/50c8d8b71b6613bb17088cf7b02319dd907d8bd05f6280e27a4199c68402/luigi-2.1.1.tar.gz",
+ "size": 1129059
+ }
+ ],
+ "1.0.2": [
+ {
+ "has_sig": false,
+ "upload_time": "2013-04-25T17:18:57",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/9a/d5/6351a5b71f2bb6501211f6fc3d5e102d72017ef289b6729610208765617f/luigi-1.0.2.tar.gz",
+ "md5_digest": "9ef8a6a5783f0bd5dbdbe4b8a889bb84",
+ "downloads": 2215,
+ "filename": "luigi-1.0.2.tar.gz",
+ "packagetype": "sdist",
+ "path": "9a/d5/6351a5b71f2bb6501211f6fc3d5e102d72017ef289b6729610208765617f/luigi-1.0.2.tar.gz",
+ "size": 78573
+ }
+ ],
+ "1.0.3": [
+ {
+ "has_sig": false,
+ "upload_time": "2013-04-25T17:20:20",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/d6/8a/d9bd49a8ce0cb8e5e26f35436e5dafab01bb4fb13d7189a59f95b52a8a7b/luigi-1.0.3.tar.gz",
+ "md5_digest": "8fb2043ccf28c6034c3b2e1c8b0a92ff",
+ "downloads": 10655,
+ "filename": "luigi-1.0.3.tar.gz",
+ "packagetype": "sdist",
+ "path": "d6/8a/d9bd49a8ce0cb8e5e26f35436e5dafab01bb4fb13d7189a59f95b52a8a7b/luigi-1.0.3.tar.gz",
+ "size": 93196
+ }
+ ],
+ "1.0.16": [
+ {
+ "has_sig": false,
+ "upload_time": "2014-05-17T16:34:18",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/be/43/d9c21e162f3412833ab57d8fb22e328dbfec9e68e562e09e612f8bb8afd0/luigi-1.0.16.tar.gz",
+ "md5_digest": "edbebf80d6c332fcd07907c14da4d326",
+ "downloads": 30433,
+ "filename": "luigi-1.0.16.tar.gz",
+ "packagetype": "sdist",
+ "path": "be/43/d9c21e162f3412833ab57d8fb22e328dbfec9e68e562e09e612f8bb8afd0/luigi-1.0.16.tar.gz",
+ "size": 277787
+ }
+ ],
+ "1.0.17": [
+ {
+ "has_sig": false,
+ "upload_time": "2014-08-26T14:32:35",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/ba/f5/b3d877f760ae4cd741ba90ca4b0fcf0527b1e7e72ec34d13a8762afbdbc0/luigi-1.0.17.tar.gz",
+ "md5_digest": "13151df79c743df21358560f0e7e9321",
+ "downloads": 3871,
+ "filename": "luigi-1.0.17.tar.gz",
+ "packagetype": "sdist",
+ "path": "ba/f5/b3d877f760ae4cd741ba90ca4b0fcf0527b1e7e72ec34d13a8762afbdbc0/luigi-1.0.17.tar.gz",
+ "size": 296199
+ }
+ ],
+ "1.0.14": [
+ {
+ "has_sig": false,
+ "upload_time": "2014-05-14T11:56:59",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/31/7a/697567f198c3187d329bd5239380595c18b1d4cec2100abb8683a5431449/luigi-1.0.14.tar.gz",
+ "md5_digest": "f9212f6cd1dc046739664b5bedcc3415",
+ "downloads": 1802,
+ "filename": "luigi-1.0.14.tar.gz",
+ "packagetype": "sdist",
+ "path": "31/7a/697567f198c3187d329bd5239380595c18b1d4cec2100abb8683a5431449/luigi-1.0.14.tar.gz",
+ "size": 277355
+ }
+ ],
+ "1.0.15": [
+ {
+ "has_sig": false,
+ "upload_time": "2014-05-14T14:18:30",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/e9/a4/229f2ba9f070bb167249989c872b1e6bd84afcaba5aa14d16f913e2a3388/luigi-1.0.15.tar.gz",
+ "md5_digest": "7222e00a048b66d6e92af253fc86810b",
+ "downloads": 1949,
+ "filename": "luigi-1.0.15.tar.gz",
+ "packagetype": "sdist",
+ "path": "e9/a4/229f2ba9f070bb167249989c872b1e6bd84afcaba5aa14d16f913e2a3388/luigi-1.0.15.tar.gz",
+ "size": 277722
+ }
+ ],
+ "1.0.12": [
+ {
+ "has_sig": false,
+ "upload_time": "2013-11-26T04:18:10",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/5a/09/38185b73e7ea6d477ea01cc85f075b77730595b1f8b0e55a4edbeac66d53/luigi-1.0.12.tar.gz",
+ "md5_digest": "58d33b2f940bd4ad2baa5281d4240345",
+ "downloads": 18087,
+ "filename": "luigi-1.0.12.tar.gz",
+ "packagetype": "sdist",
+ "path": "5a/09/38185b73e7ea6d477ea01cc85f075b77730595b1f8b0e55a4edbeac66d53/luigi-1.0.12.tar.gz",
+ "size": 238722
+ }
+ ],
+ "1.0.13": [
+ {
+ "has_sig": false,
+ "upload_time": "2014-02-03T05:44:54",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/bb/d8/ec43a5bbbf963675a198dd0c050f61df859c326b9373d26ac22bee00aa95/luigi-1.0.13.tar.gz",
+ "md5_digest": "3150d20f66026df00887625f11720acb",
+ "downloads": 5096,
+ "filename": "luigi-1.0.13.tar.gz",
+ "packagetype": "sdist",
+ "path": "bb/d8/ec43a5bbbf963675a198dd0c050f61df859c326b9373d26ac22bee00aa95/luigi-1.0.13.tar.gz",
+ "size": 293454
+ }
+ ],
+ "1.0.10": [
+ {
+ "has_sig": false,
+ "upload_time": "2013-08-09T16:06:37",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/07/c1/26b984d5f1084e57ff9207a9b1873ce0a0c3d4c1c857f20fa38e93c45b3b/luigi-1.0.10.tar.gz",
+ "md5_digest": "7f6a390a7d928f3866f13bd5be55a91d",
+ "downloads": 4379,
+ "filename": "luigi-1.0.10.tar.gz",
+ "packagetype": "sdist",
+ "path": "07/c1/26b984d5f1084e57ff9207a9b1873ce0a0c3d4c1c857f20fa38e93c45b3b/luigi-1.0.10.tar.gz",
+ "size": 228201
+ }
+ ],
+ "1.0.11": [
+ {
+ "has_sig": false,
+ "upload_time": "2013-11-21T23:07:21",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/bd/f4/8828fbced3792398065560a5d7203df45b85199f230bde9364d9ce37726e/luigi-1.0.11.tar.gz",
+ "md5_digest": "d5858aeeb5deef91ae819376ebefd83d",
+ "downloads": 2062,
+ "filename": "luigi-1.0.11.tar.gz",
+ "packagetype": "sdist",
+ "path": "bd/f4/8828fbced3792398065560a5d7203df45b85199f230bde9364d9ce37726e/luigi-1.0.11.tar.gz",
+ "size": 238741
+ }
+ ],
+ "1.0.18": [
+ {
+ "has_sig": false,
+ "upload_time": "2014-09-15T11:40:39",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/0b/9a/f51f96ca7ee9a330d6912d08c5fe237008de1c10c52114722f68d15bdee8/luigi-1.0.18.tar.gz",
+ "md5_digest": "e7cda3de5128d697ecb89b126522aa21",
+ "downloads": 2150,
+ "filename": "luigi-1.0.18.tar.gz",
+ "packagetype": "sdist",
+ "path": "0b/9a/f51f96ca7ee9a330d6912d08c5fe237008de1c10c52114722f68d15bdee8/luigi-1.0.18.tar.gz",
+ "size": 297983
+ }
+ ],
+ "1.0.19": [
+ {
+ "has_sig": false,
+ "upload_time": "2014-09-22T12:14:38",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/f5/a2/ee698ff0e301b321ffccf0a254df5e30e5ab734d23886606937f73b5ccb6/luigi-1.0.19.tar.gz",
+ "md5_digest": "3170554e32a7a630f9457d3298741538",
+ "downloads": 207006,
+ "filename": "luigi-1.0.19.tar.gz",
+ "packagetype": "sdist",
+ "path": "f5/a2/ee698ff0e301b321ffccf0a254df5e30e5ab734d23886606937f73b5ccb6/luigi-1.0.19.tar.gz",
+ "size": 300167
+ }
+ ],
+ "2.3.0": [
+ {
+ "has_sig": false,
+ "upload_time": "2016-08-12T03:20:41",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/25/64/5383d94b5b44e9c1443c1a6b857210ace8205954359f8353a50c16deb664/luigi-2.3.0.tar.gz",
+ "md5_digest": "3b7e0b4c8d684a168c97a4fb2d9340ca",
+ "downloads": 1188,
+ "filename": "luigi-2.3.0.tar.gz",
+ "packagetype": "sdist",
+ "path": "25/64/5383d94b5b44e9c1443c1a6b857210ace8205954359f8353a50c16deb664/luigi-2.3.0.tar.gz",
+ "size": 1113879
+ }
+ ],
+ "2.3.1": [
+ {
+ "has_sig": false,
+ "upload_time": "2016-08-25T02:41:26",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/55/8d/0842fbdb05a18d4a9e578f7c1661fbc719c625b1d1f0f9ceb08ea8bea518/luigi-2.3.1.tar.gz",
+ "md5_digest": "e48786e9ac71d8fd58694529d3f5539d",
+ "downloads": 7557,
+ "filename": "luigi-2.3.1.tar.gz",
+ "packagetype": "sdist",
+ "path": "55/8d/0842fbdb05a18d4a9e578f7c1661fbc719c625b1d1f0f9ceb08ea8bea518/luigi-2.3.1.tar.gz",
+ "size": 1114644
+ }
+ ],
+ "2.3.2": [
+ {
+ "has_sig": false,
+ "upload_time": "2016-09-20T09:46:25",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/d5/0b/531d2efe721a7195bd593ff2d92d41720b10dae0093f9abfd2c073560dcf/luigi-2.3.2.tar.gz",
+ "md5_digest": "cd622f6fbae981bc1b8f9b0132b189b8",
+ "downloads": 8558,
+ "filename": "luigi-2.3.2.tar.gz",
+ "packagetype": "sdist",
+ "path": "d5/0b/531d2efe721a7195bd593ff2d92d41720b10dae0093f9abfd2c073560dcf/luigi-2.3.2.tar.gz",
+ "size": 1116310
+ }
+ ],
+ "2.3.3": [
+ {
+ "has_sig": false,
+ "upload_time": "2016-10-21T04:04:56",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/80/83/f1f805266ba83964b90e31890d8f8f9ee4b82c40e9778fac350bdf830fba/luigi-2.3.3.tar.gz",
+ "md5_digest": "dea3b1cb636f7ac141c6054717728830",
+ "downloads": 7910,
+ "filename": "luigi-2.3.3.tar.gz",
+ "packagetype": "sdist",
+ "path": "80/83/f1f805266ba83964b90e31890d8f8f9ee4b82c40e9778fac350bdf830fba/luigi-2.3.3.tar.gz",
+ "size": 1119561
+ }
+ ],
+ "1.3.0": [
+ {
+ "has_sig": false,
+ "upload_time": "2015-06-26T13:19:38",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/7a/3d/da7ebf732a295098ec7b72aefd6580cc68dad461fdbce9265ddb8a3544f8/luigi-1.3.0.tar.gz",
+ "md5_digest": "948a6574e4d4e1d1d8b8a355ca0cdaf7",
+ "downloads": 44182,
+ "filename": "luigi-1.3.0.tar.gz",
+ "packagetype": "sdist",
+ "path": "7a/3d/da7ebf732a295098ec7b72aefd6580cc68dad461fdbce9265ddb8a3544f8/luigi-1.3.0.tar.gz",
+ "size": 457934
+ }
+ ],
+ "1.2.1": [
+ {
+ "has_sig": false,
+ "upload_time": "2015-05-26T10:00:32",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/3f/c7/7f5e1f5016a23c6cf2b3152bd27d994ad3b384e59e3c1bfdec444669853d/luigi-1.2.1.tar.gz",
+ "md5_digest": "a147bba0bb1999b5856f4910bf15a9c0",
+ "downloads": 25856,
+ "filename": "luigi-1.2.1.tar.gz",
+ "packagetype": "sdist",
+ "path": "3f/c7/7f5e1f5016a23c6cf2b3152bd27d994ad3b384e59e3c1bfdec444669853d/luigi-1.2.1.tar.gz",
+ "size": 449107
+ }
+ ],
+ "2.4.0": [
+ {
+ "has_sig": false,
+ "upload_time": "2016-12-02T04:52:12",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/6a/84/42bea7839bc6eee8c219775f6afe3e296a554985a0aa216fb6090478a3e5/luigi-2.4.0.tar.gz",
+ "md5_digest": "76303fa7281ac0c6a95aa9ada13acc3e",
+ "downloads": 5965,
+ "filename": "luigi-2.4.0.tar.gz",
+ "packagetype": "sdist",
+ "path": "6a/84/42bea7839bc6eee8c219775f6afe3e296a554985a0aa216fb6090478a3e5/luigi-2.4.0.tar.gz",
+ "size": 1128461
+ }
+ ],
+ "2.5.0": [
+ {
+ "has_sig": false,
+ "upload_time": "2017-01-10T07:54:38",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/9a/f2/7f7bf85e1e380375cc8a291ed648c733b4f310fe43a00073fff12bb61692/luigi-2.5.0.tar.gz",
+ "md5_digest": "26c29cd4d18381b1f148a7a43cbee335",
+ "downloads": 0,
+ "filename": "luigi-2.5.0.tar.gz",
+ "packagetype": "sdist",
+ "path": "9a/f2/7f7bf85e1e380375cc8a291ed648c733b4f310fe43a00073fff12bb61692/luigi-2.5.0.tar.gz",
+ "size": 1130701
+ }
+ ],
+ "1.0.4": [
+ {
+ "has_sig": false,
+ "upload_time": "2013-08-07T18:46:38",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/56/09/d3776490559b62d53b7cf87cb066b76b9a7f91d6749325d146c76a2adc42/luigi-1.0.4.tar.gz",
+ "md5_digest": "d5eef08fb8f76875bc28680ec72511f8",
+ "downloads": 2175,
+ "filename": "luigi-1.0.4.tar.gz",
+ "packagetype": "sdist",
+ "path": "56/09/d3776490559b62d53b7cf87cb066b76b9a7f91d6749325d146c76a2adc42/luigi-1.0.4.tar.gz",
+ "size": 71168
+ }
+ ],
+ "2.6.0": [
+ {
+ "has_sig": false,
+ "upload_time": "2017-02-10T06:57:18",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/9f/aa/5067601c565d61c8e1f172035eee4f1d50f25a193b9041f17ebc6fff5764/luigi-2.6.0.tar.gz",
+ "md5_digest": "8c36cf3d37525ccc57f6ecc24431bdef",
+ "downloads": 0,
+ "filename": "luigi-2.6.0.tar.gz",
+ "packagetype": "sdist",
+ "path": "9f/aa/5067601c565d61c8e1f172035eee4f1d50f25a193b9041f17ebc6fff5764/luigi-2.6.0.tar.gz",
+ "size": 1158747
+ }
+ ],
+ "1.0.24": [
+ {
+ "has_sig": false,
+ "upload_time": "2015-02-11T12:01:07",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/3c/a5/3bc272eb6317147ddaf8c0c3bf7ba47a684216f5e16c4fdf80f05ac94d60/luigi-1.0.24.tar.gz",
+ "md5_digest": "44c6f413dff37e6cd295e696f2cdea19",
+ "downloads": 23418,
+ "filename": "luigi-1.0.24.tar.gz",
+ "packagetype": "sdist",
+ "path": "3c/a5/3bc272eb6317147ddaf8c0c3bf7ba47a684216f5e16c4fdf80f05ac94d60/luigi-1.0.24.tar.gz",
+ "size": 333339
+ }
+ ],
+ "1.0.23": [
+ {
+ "has_sig": false,
+ "upload_time": "2015-02-10T11:53:49",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/2e/5c/d53458d78415079fef6bc2231f7b5f5e5876e90f39cc2c57a054379df0cc/luigi-1.0.23.tar.gz",
+ "md5_digest": "0c9d7dd091b913f9076b5517dc41cd91",
+ "downloads": 2542,
+ "filename": "luigi-1.0.23.tar.gz",
+ "packagetype": "sdist",
+ "path": "2e/5c/d53458d78415079fef6bc2231f7b5f5e5876e90f39cc2c57a054379df0cc/luigi-1.0.23.tar.gz",
+ "size": 333182
+ }
+ ],
+ "1.0.22": [
+ {
+ "has_sig": false,
+ "upload_time": "2015-02-10T04:20:16",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/b7/8b/d7751ae52e30e1b872bcaaf4626b202e0fc61c2c91fef91912b6e901545e/luigi-1.0.22.tar.gz",
+ "md5_digest": "10762c7d1999babdb38471a26b1d2880",
+ "downloads": 1072,
+ "filename": "luigi-1.0.22.tar.gz",
+ "packagetype": "sdist",
+ "path": "b7/8b/d7751ae52e30e1b872bcaaf4626b202e0fc61c2c91fef91912b6e901545e/luigi-1.0.22.tar.gz",
+ "size": 333175
+ }
+ ],
+ "1.0.21": [],
+ "1.0.20": [
+ {
+ "has_sig": false,
+ "upload_time": "2015-01-21T16:27:35",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/2b/88/804830f0c78ebe1a2b1dfbf723bfcd97f6822f4e139da5909cd87baf2374/luigi-1.0.20.tar.gz",
+ "md5_digest": "f1edc408bb19ffaf18a88693abc0d765",
+ "downloads": 6245,
+ "filename": "luigi-1.0.20.tar.gz",
+ "packagetype": "sdist",
+ "path": "2b/88/804830f0c78ebe1a2b1dfbf723bfcd97f6822f4e139da5909cd87baf2374/luigi-1.0.20.tar.gz",
+ "size": 324700
+ }
+ ]
+ },
+ "urls": [
+ {
+ "has_sig": false,
+ "upload_time": "2017-02-10T06:57:18",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/9f/aa/5067601c565d61c8e1f172035eee4f1d50f25a193b9041f17ebc6fff5764/luigi-2.6.0.tar.gz",
+ "md5_digest": "8c36cf3d37525ccc57f6ecc24431bdef",
+ "downloads": 0,
+ "filename": "luigi-2.6.0.tar.gz",
+ "packagetype": "sdist",
+ "path": "9f/aa/5067601c565d61c8e1f172035eee4f1d50f25a193b9041f17ebc6fff5764/luigi-2.6.0.tar.gz",
+ "size": 1158747
+ }
+ ]
+}
diff --git a/uv/spec/fixtures/pypi/pypi_response_description_source.json b/uv/spec/fixtures/pypi/pypi_response_description_source.json
new file mode 100644
index 00000000000..48ac4bcba7b
--- /dev/null
+++ b/uv/spec/fixtures/pypi/pypi_response_description_source.json
@@ -0,0 +1,584 @@
+{
+ "info": {
+ "maintainer": "",
+ "docs_url": "http://pythonhosted.org/six/",
+ "requires_python": "",
+ "maintainer_email": "",
+ "cheesecake_code_kwalitee_id": null,
+ "keywords": "",
+ "package_url": "http://pypi.org/pypi/six",
+ "author": "Benjamin Peterson",
+ "author_email": "benjamin@python.org",
+ "download_url": "",
+ "platform": "",
+ "version": "1.11.0",
+ "cheesecake_documentation_id": null,
+ "_pypi_hidden": false,
+ "description": ".. image:: http://img.shields.io/pypi/v/six.svg\n :target: https://pypi.org/pypi/six\n\n.. image:: https://travis-ci.org/benjaminp/six.svg?branch=master\n :target: https://travis-ci.org/benjaminp/six\n\n.. image:: http://img.shields.io/badge/license-MIT-green.svg\n :target: https://github.com/benjaminp/six/blob/master/LICENSE\n\nSix is a Python 2 and 3 compatibility library. It provides utility functions\nfor smoothing over the differences between the Python versions with the goal of\nwriting Python code that is compatible on both Python versions. See the\ndocumentation for more information on what is provided.\n\nSix supports every Python version since 2.6. It is contained in only one Python\nfile, so it can be easily copied into your project. (The copyright and license\nnotice must be retained.)\n\nOnline documentation is at http://six.rtfd.org.\n\nBugs can be reported to https://github.com/benjaminp/six. The code can also\nbe found there.\n\nFor questions about six or porting in general, email the python-porting mailing\nlist: https://mail.python.org/mailman/listinfo/python-porting\n\n\n",
+ "release_url": "http://pypi.org/pypi/six/1.11.0",
+ "downloads": {
+ "last_month": 0,
+ "last_week": 0,
+ "last_day": 0
+ },
+ "_pypi_ordering": 22,
+ "classifiers": [
+ "Intended Audience :: Developers",
+ "License :: OSI Approved :: MIT License",
+ "Programming Language :: Python :: 2",
+ "Programming Language :: Python :: 3",
+ "Topic :: Software Development :: Libraries",
+ "Topic :: Utilities"
+ ],
+ "name": "six",
+ "bugtrack_url": null,
+ "license": "MIT",
+ "summary": "Python 2 and 3 compatibility utilities",
+ "home_page": "http://pypi.org/pypi/six/",
+ "cheesecake_installability_id": null
+ },
+ "releases": {
+ "1.1.0": [
+ {
+ "has_sig": false,
+ "upload_time": "2011-11-23T06:43:24",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/54/d4/8f7d631f1c3defa2ff4bd7c3daddcc5ed6eb9df7631f3cf24cc376aa3231/six-1.1.0.tar.gz",
+ "md5_digest": "9e8099b57cd27493a6988e9c9b313e23",
+ "downloads": 255135,
+ "filename": "six-1.1.0.tar.gz",
+ "packagetype": "sdist",
+ "path": "54/d4/8f7d631f1c3defa2ff4bd7c3daddcc5ed6eb9df7631f3cf24cc376aa3231/six-1.1.0.tar.gz",
+ "size": 12573
+ }
+ ],
+ "1.0.0": [
+ {
+ "has_sig": false,
+ "upload_time": "2011-03-15T16:55:50",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/a6/af/4506a069312018665b8936e5d51b3aa013971ef65eab5231ef151a482dcd/six-1.0.0.tar.gz",
+ "md5_digest": "37c7ff036fdff2b1bb8d55e49ccb3b44",
+ "downloads": 21113,
+ "filename": "six-1.0.0.tar.gz",
+ "packagetype": "sdist",
+ "path": "a6/af/4506a069312018665b8936e5d51b3aa013971ef65eab5231ef151a482dcd/six-1.0.0.tar.gz",
+ "size": 11694
+ }
+ ],
+ "0.9.1": [
+ {
+ "has_sig": false,
+ "upload_time": "2010-06-30T22:32:11",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/4e/02/f08545a99829a04e841b6443267f216629c723c23fb9cfd17c99c068e33a/six-0.9.1.tar.gz",
+ "md5_digest": "1b249e0011355722f569406135a8ac93",
+ "downloads": 2950,
+ "filename": "six-0.9.1.tar.gz",
+ "packagetype": "sdist",
+ "path": "4e/02/f08545a99829a04e841b6443267f216629c723c23fb9cfd17c99c068e33a/six-0.9.1.tar.gz",
+ "size": 13653
+ }
+ ],
+ "0.9.0": [
+ {
+ "has_sig": true,
+ "upload_time": "2010-06-29T19:56:36",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/0e/f9/66471f9b7e9291cca697b2e61a10645a537f389a9d5c0679d50dd86b20f7/six-0.9.0.tar.gz",
+ "md5_digest": "5ce2947347101b9f54674c19ef88233d",
+ "downloads": 3259,
+ "filename": "six-0.9.0.tar.gz",
+ "packagetype": "sdist",
+ "path": "0e/f9/66471f9b7e9291cca697b2e61a10645a537f389a9d5c0679d50dd86b20f7/six-0.9.0.tar.gz",
+ "size": 13292
+ }
+ ],
+ "1.6.0": [
+ {
+ "has_sig": false,
+ "upload_time": "2014-03-14T03:11:13",
+ "comment_text": "",
+ "python_version": "3.3",
+ "url": "https://pypi.org/packages/54/45/8b5eef1ba0b79acbdab01435359f37ae13dc6c4aafaa444b805e3867386d/six-1.6.0-py2.py3-none-any.whl",
+ "md5_digest": "e2755cf8a1d8e4eda44a8e3436c458ca",
+ "downloads": 6271,
+ "filename": "six-1.6.0-py2.py3-none-any.whl",
+ "packagetype": "bdist_wheel",
+ "path": "54/45/8b5eef1ba0b79acbdab01435359f37ae13dc6c4aafaa444b805e3867386d/six-1.6.0-py2.py3-none-any.whl",
+ "size": 8513
+ },
+ {
+ "has_sig": false,
+ "upload_time": "2014-03-14T03:11:10",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/02/c3/8e2a38edaac777ee2bbe479b3a65b020ade549efd6a224c2f4e95c818799/six-1.6.0.tar.gz",
+ "md5_digest": "eb22a24e8be9497dd71930bf2321b6ec",
+ "downloads": 4359,
+ "filename": "six-1.6.0.tar.gz",
+ "packagetype": "sdist",
+ "path": "02/c3/8e2a38edaac777ee2bbe479b3a65b020ade549efd6a224c2f4e95c818799/six-1.6.0.tar.gz",
+ "size": 24716
+ }
+ ],
+ "1.6.1": [
+ {
+ "has_sig": false,
+ "upload_time": "2014-03-14T03:39:37",
+ "comment_text": "",
+ "python_version": "3.3",
+ "url": "https://pypi.org/packages/ba/19/aa48edcff9d0c396a4d009d362d0a0a1ac3db6f9d7d5736e0175b94d7ef8/six-1.6.1-py2.py3-none-any.whl",
+ "md5_digest": "ca195cc2271b03ae1c8750a88081c7f1",
+ "downloads": 1620090,
+ "filename": "six-1.6.1-py2.py3-none-any.whl",
+ "packagetype": "bdist_wheel",
+ "path": "ba/19/aa48edcff9d0c396a4d009d362d0a0a1ac3db6f9d7d5736e0175b94d7ef8/six-1.6.1-py2.py3-none-any.whl",
+ "size": 8557
+ },
+ {
+ "has_sig": false,
+ "upload_time": "2014-03-14T03:39:35",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/e8/70/b9c441d8c02b70eb3bf923c49944b8fc656f78a43c084d2a98534d7404e2/six-1.6.1.tar.gz",
+ "md5_digest": "07d606ac08595d795bf926cc9985674f",
+ "downloads": 2909685,
+ "filename": "six-1.6.1.tar.gz",
+ "packagetype": "sdist",
+ "path": "e8/70/b9c441d8c02b70eb3bf923c49944b8fc656f78a43c084d2a98534d7404e2/six-1.6.1.tar.gz",
+ "size": 24792
+ }
+ ],
+ "1.9.0": [
+ {
+ "has_sig": false,
+ "upload_time": "2015-01-02T16:38:13",
+ "comment_text": "",
+ "python_version": "3.3",
+ "url": "https://pypi.org/packages/10/e3/a7f8eea80a9fa8358c1cd89ef489bc03675e69e54ed2982cd6f2a28d8295/six-1.9.0-py2.py3-none-any.whl",
+ "md5_digest": "9ac7e129a80f72d6fc1f0216f6e9627b",
+ "downloads": 19614806,
+ "filename": "six-1.9.0-py2.py3-none-any.whl",
+ "packagetype": "bdist_wheel",
+ "path": "10/e3/a7f8eea80a9fa8358c1cd89ef489bc03675e69e54ed2982cd6f2a28d8295/six-1.9.0-py2.py3-none-any.whl",
+ "size": 10222
+ },
+ {
+ "has_sig": false,
+ "upload_time": "2015-01-02T16:38:06",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/16/64/1dc5e5976b17466fd7d712e59cbe9fb1e18bec153109e5ba3ed6c9102f1a/six-1.9.0.tar.gz",
+ "md5_digest": "476881ef4012262dfc8adc645ee786c4",
+ "downloads": 12925525,
+ "filename": "six-1.9.0.tar.gz",
+ "packagetype": "sdist",
+ "path": "16/64/1dc5e5976b17466fd7d712e59cbe9fb1e18bec153109e5ba3ed6c9102f1a/six-1.9.0.tar.gz",
+ "size": 29127
+ }
+ ],
+ "1.7.3": [
+ {
+ "has_sig": false,
+ "upload_time": "2014-06-29T19:30:30",
+ "comment_text": "",
+ "python_version": "3.3",
+ "url": "https://pypi.org/packages/2e/a4/6dcb84af409b7bc0c258a0d6bd7e14231724d9a46b750c048f09d74d870c/six-1.7.3-py2.py3-none-any.whl",
+ "md5_digest": "5f34fe522765d398b21decdce62ebd1d",
+ "downloads": 2597388,
+ "filename": "six-1.7.3-py2.py3-none-any.whl",
+ "packagetype": "bdist_wheel",
+ "path": "2e/a4/6dcb84af409b7bc0c258a0d6bd7e14231724d9a46b750c048f09d74d870c/six-1.7.3-py2.py3-none-any.whl",
+ "size": 9503
+ },
+ {
+ "has_sig": false,
+ "upload_time": "2014-06-29T19:30:27",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/2b/4a/233721f6c6afeed5a2034f617f120fa646da935039f08e67ab8dc008a3e6/six-1.7.3.tar.gz",
+ "md5_digest": "784c6e5541c3c4952de9c0a966a0a80b",
+ "downloads": 2700212,
+ "filename": "six-1.7.3.tar.gz",
+ "packagetype": "sdist",
+ "path": "2b/4a/233721f6c6afeed5a2034f617f120fa646da935039f08e67ab8dc008a3e6/six-1.7.3.tar.gz",
+ "size": 26339
+ }
+ ],
+ "1.7.2": [
+ {
+ "has_sig": false,
+ "upload_time": "2014-06-09T04:15:38",
+ "comment_text": "",
+ "python_version": "py2.py3",
+ "url": "https://pypi.org/packages/6b/30/839b8059d1225dbd3a0dd97c3c370bbb978cde505e160b30515fb7be17d8/six-1.7.2-py2.py3-none-any.whl",
+ "md5_digest": "0e10f8d8e65257408e4428632859dad9",
+ "downloads": 520900,
+ "filename": "six-1.7.2-py2.py3-none-any.whl",
+ "packagetype": "bdist_wheel",
+ "path": "6b/30/839b8059d1225dbd3a0dd97c3c370bbb978cde505e160b30515fb7be17d8/six-1.7.2-py2.py3-none-any.whl",
+ "size": 9614
+ },
+ {
+ "has_sig": false,
+ "upload_time": "2014-06-09T04:15:44",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/a4/ed/a1410f4a3ae1492d87cbc7acdeea819db3caf6e526ef7032dd6fe50d2083/six-1.7.2.tar.gz",
+ "md5_digest": "4c26276583b01dfc73474cb32327af91",
+ "downloads": 672500,
+ "filename": "six-1.7.2.tar.gz",
+ "packagetype": "sdist",
+ "path": "a4/ed/a1410f4a3ae1492d87cbc7acdeea819db3caf6e526ef7032dd6fe50d2083/six-1.7.2.tar.gz",
+ "size": 26399
+ }
+ ],
+ "1.7.1": [
+ {
+ "has_sig": false,
+ "upload_time": "2014-06-09T03:57:48",
+ "comment_text": "",
+ "python_version": "py2.py3",
+ "url": "https://pypi.org/packages/aa/ec/e6954e19e617c1b9860325f0995d456d8416c84a6cb9bce1c10998280b59/six-1.7.1-py2.py3-none-any.whl",
+ "md5_digest": "c3c1e251733acc9db947e75c9a02cf06",
+ "downloads": 2001,
+ "filename": "six-1.7.1-py2.py3-none-any.whl",
+ "packagetype": "bdist_wheel",
+ "path": "aa/ec/e6954e19e617c1b9860325f0995d456d8416c84a6cb9bce1c10998280b59/six-1.7.1-py2.py3-none-any.whl",
+ "size": 9610
+ },
+ {
+ "has_sig": false,
+ "upload_time": "2014-06-09T03:57:54",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/1b/2a/ad686ae156581a70a7be28e7762f7d956bec30d62dafe9295b78dc019692/six-1.7.1.tar.gz",
+ "md5_digest": "f9fbad970c6e855cabde7ec1144b9058",
+ "downloads": 3525,
+ "filename": "six-1.7.1.tar.gz",
+ "packagetype": "sdist",
+ "path": "1b/2a/ad686ae156581a70a7be28e7762f7d956bec30d62dafe9295b78dc019692/six-1.7.1.tar.gz",
+ "size": 26375
+ }
+ ],
+ "1.7.0": [
+ {
+ "has_sig": false,
+ "upload_time": "2014-06-08T02:35:46",
+ "comment_text": "",
+ "python_version": "py2.py3",
+ "url": "https://pypi.org/packages/20/0a/617bf23511160454995bf1cbe6789f22beeb8b49c1f3b1bbf4b5cd6a55ca/six-1.7.0-py2.py3-none-any.whl",
+ "md5_digest": "e5ca7e89cc79d755ea128fc7e2cb136e",
+ "downloads": 32104,
+ "filename": "six-1.7.0-py2.py3-none-any.whl",
+ "packagetype": "bdist_wheel",
+ "path": "20/0a/617bf23511160454995bf1cbe6789f22beeb8b49c1f3b1bbf4b5cd6a55ca/six-1.7.0-py2.py3-none-any.whl",
+ "size": 9340
+ },
+ {
+ "has_sig": false,
+ "upload_time": "2014-06-08T02:35:49",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/7e/16/792311d76b8e23da84e1b177fb973679de1c963391d0dcd7e963634bed4b/six-1.7.0.tar.gz",
+ "md5_digest": "92f7210da3db1e988979fa394aa41d7a",
+ "downloads": 36330,
+ "filename": "six-1.7.0.tar.gz",
+ "packagetype": "sdist",
+ "path": "7e/16/792311d76b8e23da84e1b177fb973679de1c963391d0dcd7e963634bed4b/six-1.7.0.tar.gz",
+ "size": 26124
+ }
+ ],
+ "1.4.0": [
+ {
+ "has_sig": false,
+ "upload_time": "2013-09-01T21:14:06",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/99/25/2df8760d6902620cfca85e36f07de491d14f2c325ecc01c1a5590d8af22d/six-1.4.0.tar.gz",
+ "md5_digest": "5fcab6a067b5ebf68ede2f4d02fe7547",
+ "downloads": 39316,
+ "filename": "six-1.4.0.tar.gz",
+ "packagetype": "sdist",
+ "path": "99/25/2df8760d6902620cfca85e36f07de491d14f2c325ecc01c1a5590d8af22d/six-1.4.0.tar.gz",
+ "size": 21367
+ }
+ ],
+ "1.4.1": [
+ {
+ "has_sig": false,
+ "upload_time": "2013-09-02T13:12:05",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/4e/aa/73683ca0c4237891e33562e3f55bcaab972869959b97b397637519d92035/six-1.4.1.tar.gz",
+ "md5_digest": "bdbb9e12d3336c198695aa4cf3a61d62",
+ "downloads": 3294260,
+ "filename": "six-1.4.1.tar.gz",
+ "packagetype": "sdist",
+ "path": "4e/aa/73683ca0c4237891e33562e3f55bcaab972869959b97b397637519d92035/six-1.4.1.tar.gz",
+ "size": 21409
+ }
+ ],
+ "0.9.2": [
+ {
+ "has_sig": false,
+ "upload_time": "2010-07-05T00:42:38",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/af/33/fa2097ac4bc7a9672517fdcb982bc7454fdd113f49f7ab353025b906a119/six-0.9.2.tar.gz",
+ "md5_digest": "92ea7c870396dd9222029a188c6bbd7f",
+ "downloads": 3266,
+ "filename": "six-0.9.2.tar.gz",
+ "packagetype": "sdist",
+ "path": "af/33/fa2097ac4bc7a9672517fdcb982bc7454fdd113f49f7ab353025b906a119/six-0.9.2.tar.gz",
+ "size": 13658
+ }
+ ],
+ "1.5.1": [
+ {
+ "has_sig": false,
+ "upload_time": "2014-01-05T05:15:22",
+ "comment_text": "",
+ "python_version": "3.3",
+ "url": "https://pypi.org/packages/60/84/72c628d5a4efffb23e2fb46cdbf8ee669046d8208ba5dab08f989b7bfe9c/six-1.5.1-py2.py3-none-any.whl",
+ "md5_digest": "2064b715201fa76a55dea75675ee19f2",
+ "downloads": 46598,
+ "filename": "six-1.5.1-py2.py3-none-any.whl",
+ "packagetype": "bdist_wheel",
+ "path": "60/84/72c628d5a4efffb23e2fb46cdbf8ee669046d8208ba5dab08f989b7bfe9c/six-1.5.1-py2.py3-none-any.whl",
+ "size": 8396
+ },
+ {
+ "has_sig": false,
+ "upload_time": "2014-01-05T05:15:14",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/0b/5e/4b3f417a85d9cd30b172a1512a2d3cdd0ffb05a5deacb8adf2ef30db100d/six-1.5.1.tar.gz",
+ "md5_digest": "bb00c982fc0ec0dd6a760500b0941fa9",
+ "downloads": 45202,
+ "filename": "six-1.5.1.tar.gz",
+ "packagetype": "sdist",
+ "path": "0b/5e/4b3f417a85d9cd30b172a1512a2d3cdd0ffb05a5deacb8adf2ef30db100d/six-1.5.1.tar.gz",
+ "size": 24000
+ }
+ ],
+ "1.5.0": [
+ {
+ "has_sig": false,
+ "upload_time": "2014-01-05T00:56:10",
+ "comment_text": "",
+ "python_version": "3.3",
+ "url": "https://pypi.org/packages/ca/15/e62a66024dded9640f8d39112330e6b108e7ab21a1b8618c2d1e2eea7e1d/six-1.5.0-py2.py3-none-any.whl",
+ "md5_digest": "3307efe2bc4ca8556befc9afe297c530",
+ "downloads": 5446,
+ "filename": "six-1.5.0-py2.py3-none-any.whl",
+ "packagetype": "bdist_wheel",
+ "path": "ca/15/e62a66024dded9640f8d39112330e6b108e7ab21a1b8618c2d1e2eea7e1d/six-1.5.0-py2.py3-none-any.whl",
+ "size": 8186
+ },
+ {
+ "has_sig": false,
+ "upload_time": "2014-01-05T00:56:07",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/0f/dd/379fa572b72da0b482545116139529af8da92e686ea136271beecddd4e81/six-1.5.0.tar.gz",
+ "md5_digest": "72b33ff89f3b2f21dd2cb28fb94f7031",
+ "downloads": 8447,
+ "filename": "six-1.5.0.tar.gz",
+ "packagetype": "sdist",
+ "path": "0f/dd/379fa572b72da0b482545116139529af8da92e686ea136271beecddd4e81/six-1.5.0.tar.gz",
+ "size": 23775
+ }
+ ],
+ "1.5.2": [
+ {
+ "has_sig": false,
+ "upload_time": "2014-01-06T15:57:56",
+ "comment_text": "",
+ "python_version": "3.3",
+ "url": "https://pypi.org/packages/c7/a4/35520d20a8e4b3c28c9db705fffd4c7053e0236928951da32167e5078faa/six-1.5.2-py2.py3-none-any.whl",
+ "md5_digest": "ba32222ad0c5c7057a7c42e66e81289d",
+ "downloads": 773183,
+ "filename": "six-1.5.2-py2.py3-none-any.whl",
+ "packagetype": "bdist_wheel",
+ "path": "c7/a4/35520d20a8e4b3c28c9db705fffd4c7053e0236928951da32167e5078faa/six-1.5.2-py2.py3-none-any.whl",
+ "size": 8429
+ },
+ {
+ "has_sig": false,
+ "upload_time": "2014-01-06T15:57:54",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/1d/8e/220ce5a36dac3aabccee871a34561ceba82ce14b53760143cf5e01bb4d2c/six-1.5.2.tar.gz",
+ "md5_digest": "322b86d0c50a7d165c05600154cecc0a",
+ "downloads": 2208524,
+ "filename": "six-1.5.2.tar.gz",
+ "packagetype": "sdist",
+ "path": "1d/8e/220ce5a36dac3aabccee871a34561ceba82ce14b53760143cf5e01bb4d2c/six-1.5.2.tar.gz",
+ "size": 24081
+ }
+ ],
+ "1.0b1": [
+ {
+ "has_sig": false,
+ "upload_time": "2010-11-20T22:57:30",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/8b/08/8f569ab2c81c1443ce43e29df2e7eec1ab7f005455f6c193793728b00f04/six-1.0b1.tar.gz",
+ "md5_digest": "cbfcc64af1f27162a6a6b5510e262c9d",
+ "downloads": 3187,
+ "filename": "six-1.0b1.tar.gz",
+ "packagetype": "sdist",
+ "path": "8b/08/8f569ab2c81c1443ce43e29df2e7eec1ab7f005455f6c193793728b00f04/six-1.0b1.tar.gz",
+ "size": 11251
+ }
+ ],
+ "1.3.0": [
+ {
+ "has_sig": false,
+ "upload_time": "2013-03-18T20:40:13",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/02/f8/d16f06e49b0d2ef40548bf42826f926c8964ad3b1d00f8098dcc6ef15aea/six-1.3.0.tar.gz",
+ "md5_digest": "ec47fe6070a8a64c802363d2c2b1e2ee",
+ "downloads": 1620124,
+ "filename": "six-1.3.0.tar.gz",
+ "packagetype": "sdist",
+ "path": "02/f8/d16f06e49b0d2ef40548bf42826f926c8964ad3b1d00f8098dcc6ef15aea/six-1.3.0.tar.gz",
+ "size": 17701
+ }
+ ],
+ "1.2.0": [
+ {
+ "has_sig": false,
+ "upload_time": "2012-08-28T19:55:23",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/e9/b4/0ccbc17cd49a812ab8363058bb12f0134cf2d3ba752391f309ddf567ae97/six-1.2.0.tar.gz",
+ "md5_digest": "2a5d1afc79912832ac78fd38e3d75d7e",
+ "downloads": 814231,
+ "filename": "six-1.2.0.tar.gz",
+ "packagetype": "sdist",
+ "path": "e9/b4/0ccbc17cd49a812ab8363058bb12f0134cf2d3ba752391f309ddf567ae97/six-1.2.0.tar.gz",
+ "size": 15316
+ }
+ ],
+ "1.11.0": [
+ {
+ "has_sig": false,
+ "upload_time": "2017-09-17T18:46:53",
+ "comment_text": "",
+ "python_version": "py2.py3",
+ "url": "https://pypi.org/packages/67/4b/141a581104b1f6397bfa78ac9d43d8ad29a7ca43ea90a2d863fe3056e86a/six-1.11.0-py2.py3-none-any.whl",
+ "md5_digest": "866ab722be6bdfed6830f3179af65468",
+ "downloads": 0,
+ "filename": "six-1.11.0-py2.py3-none-any.whl",
+ "packagetype": "bdist_wheel",
+ "path": "67/4b/141a581104b1f6397bfa78ac9d43d8ad29a7ca43ea90a2d863fe3056e86a/six-1.11.0-py2.py3-none-any.whl",
+ "size": 10702
+ },
+ {
+ "has_sig": false,
+ "upload_time": "2017-09-17T18:46:54",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/16/d8/bc6316cf98419719bd59c91742194c111b6f2e85abac88e496adefaf7afe/six-1.11.0.tar.gz",
+ "md5_digest": "d12789f9baf7e9fb2524c0c64f1773f8",
+ "downloads": 0,
+ "filename": "six-1.11.0.tar.gz",
+ "packagetype": "sdist",
+ "path": "16/d8/bc6316cf98419719bd59c91742194c111b6f2e85abac88e496adefaf7afe/six-1.11.0.tar.gz",
+ "size": 29860
+ }
+ ],
+ "1.8.0": [
+ {
+ "has_sig": false,
+ "upload_time": "2014-09-11T21:48:44",
+ "comment_text": "",
+ "python_version": "py2.py3",
+ "url": "https://pypi.org/packages/a2/4b/2b4532b4eba116a02fc0b5e0b3540a073a61c003b7b6293b7b884afa8ff1/six-1.8.0-py2.py3-none-any.whl",
+ "md5_digest": "2f5f96148c68f3c1611f489678a8b445",
+ "downloads": 4885942,
+ "filename": "six-1.8.0-py2.py3-none-any.whl",
+ "packagetype": "bdist_wheel",
+ "path": "a2/4b/2b4532b4eba116a02fc0b5e0b3540a073a61c003b7b6293b7b884afa8ff1/six-1.8.0-py2.py3-none-any.whl",
+ "size": 9697
+ },
+ {
+ "has_sig": false,
+ "upload_time": "2014-09-11T21:48:46",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/11/3f/2b3c217c5427cdd12619024b1ee1b04d49e27fde5c29df2a0b92c26677c2/six-1.8.0.tar.gz",
+ "md5_digest": "1626eb24cc889110c38f7e786ec69885",
+ "downloads": 4826642,
+ "filename": "six-1.8.0.tar.gz",
+ "packagetype": "sdist",
+ "path": "11/3f/2b3c217c5427cdd12619024b1ee1b04d49e27fde5c29df2a0b92c26677c2/six-1.8.0.tar.gz",
+ "size": 26925
+ }
+ ],
+ "1.10.0": [
+ {
+ "has_sig": false,
+ "upload_time": "2015-10-07T03:17:20",
+ "comment_text": "",
+ "python_version": "py2.py3",
+ "url": "https://pypi.org/packages/c8/0a/b6723e1bc4c516cb687841499455a8505b44607ab535be01091c0f24f079/six-1.10.0-py2.py3-none-any.whl",
+ "md5_digest": "3ab558cf5d4f7a72611d59a81a315dc8",
+ "downloads": 37746177,
+ "filename": "six-1.10.0-py2.py3-none-any.whl",
+ "packagetype": "bdist_wheel",
+ "path": "c8/0a/b6723e1bc4c516cb687841499455a8505b44607ab535be01091c0f24f079/six-1.10.0-py2.py3-none-any.whl",
+ "size": 10341
+ },
+ {
+ "has_sig": false,
+ "upload_time": "2015-10-07T03:17:49",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/b3/b2/238e2590826bfdd113244a40d9d3eb26918bd798fc187e2360a8367068db/six-1.10.0.tar.gz",
+ "md5_digest": "34eed507548117b2ab523ab14b2f8b55",
+ "downloads": 10705137,
+ "filename": "six-1.10.0.tar.gz",
+ "packagetype": "sdist",
+ "path": "b3/b2/238e2590826bfdd113244a40d9d3eb26918bd798fc187e2360a8367068db/six-1.10.0.tar.gz",
+ "size": 29630
+ }
+ ]
+ },
+ "urls": [
+ {
+ "has_sig": false,
+ "upload_time": "2017-09-17T18:46:53",
+ "comment_text": "",
+ "python_version": "py2.py3",
+ "url": "https://pypi.org/packages/67/4b/141a581104b1f6397bfa78ac9d43d8ad29a7ca43ea90a2d863fe3056e86a/six-1.11.0-py2.py3-none-any.whl",
+ "md5_digest": "866ab722be6bdfed6830f3179af65468",
+ "downloads": 0,
+ "filename": "six-1.11.0-py2.py3-none-any.whl",
+ "packagetype": "bdist_wheel",
+ "path": "67/4b/141a581104b1f6397bfa78ac9d43d8ad29a7ca43ea90a2d863fe3056e86a/six-1.11.0-py2.py3-none-any.whl",
+ "size": 10702
+ },
+ {
+ "has_sig": false,
+ "upload_time": "2017-09-17T18:46:54",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/16/d8/bc6316cf98419719bd59c91742194c111b6f2e85abac88e496adefaf7afe/six-1.11.0.tar.gz",
+ "md5_digest": "d12789f9baf7e9fb2524c0c64f1773f8",
+ "downloads": 0,
+ "filename": "six-1.11.0.tar.gz",
+ "packagetype": "sdist",
+ "path": "16/d8/bc6316cf98419719bd59c91742194c111b6f2e85abac88e496adefaf7afe/six-1.11.0.tar.gz",
+ "size": 29860
+ }
+ ]
+}
diff --git a/uv/spec/fixtures/pypi/pypi_response_extras.json b/uv/spec/fixtures/pypi/pypi_response_extras.json
new file mode 100644
index 00000000000..18487c623e0
--- /dev/null
+++ b/uv/spec/fixtures/pypi/pypi_response_extras.json
@@ -0,0 +1,4160 @@
+{
+ "info":{
+ "author":"Ask Solem",
+ "author_email":"auvipy@gmail.com",
+ "bugtrack_url":null,
+ "classifiers":[
+ "Development Status :: 5 - Production/Stable",
+ "License :: OSI Approved :: BSD License",
+ "Operating System :: OS Independent",
+ "Programming Language :: Python",
+ "Programming Language :: Python :: 2",
+ "Programming Language :: Python :: 2.7",
+ "Programming Language :: Python :: 3",
+ "Programming Language :: Python :: 3.5",
+ "Programming Language :: Python :: 3.6",
+ "Programming Language :: Python :: 3.7",
+ "Programming Language :: Python :: 3.8",
+ "Programming Language :: Python :: Implementation :: CPython",
+ "Programming Language :: Python :: Implementation :: PyPy",
+ "Topic :: Software Development :: Object Brokering",
+ "Topic :: System :: Distributed Computing"
+ ],
+ "description":".. image:: http://docs.celeryproject.org/en/latest/_images/celery-banner-small.png\n\n|build-status| |coverage| |license| |wheel| |pyversion| |pyimp| |ocbackerbadge| |ocsponsorbadge|\n\n:Version: 4.4.0 (cliffs)\n:Web: http://celeryproject.org/\n:Download: https://pypi.org/project/celery/\n:Source: https://github.com/celery/celery/\n:Keywords: task, queue, job, async, rabbitmq, amqp, redis,\n python, distributed, actors\n\nDonations\n=========\n\nThis project relies on your generous donations.\n\nIf you are using Celery to create a commercial product, please consider becoming our `backer`_ or our `sponsor`_ to ensure Celery's future.\n\n.. _`backer`: https://opencollective.com/celery#backer\n.. _`sponsor`: https://opencollective.com/celery#sponsor\n\nFor enterprise\n==============\n\nAvailable as part of the Tidelift Subscription.\n\nThe maintainers of ``celery`` and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. `Learn more. `_\n\nWhat's a Task Queue?\n====================\n\nTask queues are used as a mechanism to distribute work across threads or\nmachines.\n\nA task queue's input is a unit of work, called a task, dedicated worker\nprocesses then constantly monitor the queue for new work to perform.\n\nCelery communicates via messages, usually using a broker\nto mediate between clients and workers. To initiate a task a client puts a\nmessage on the queue, the broker then delivers the message to a worker.\n\nA Celery system can consist of multiple workers and brokers, giving way\nto high availability and horizontal scaling.\n\nCelery is written in Python, but the protocol can be implemented in any\nlanguage. In addition to Python there's node-celery_ for Node.js,\na `PHP client`_ and `gocelery`_ for golang.\n\nLanguage interoperability can also be achieved by using webhooks\nin such a way that the client enqueues an URL to be requested by a worker.\n\n.. _node-celery: https://github.com/mher/node-celery\n.. _`PHP client`: https://github.com/gjedeer/celery-php\n.. _`gocelery`: https://github.com/gocelery/gocelery\n\nWhat do I need?\n===============\n\nCelery version 4.3 runs on,\n\n- Python (2.7, 3.8, 3.5, 3.6, 3.7)\n- PyPy2.7 (7.2)\n- PyPy3.5 (7.1)\n- PyPy3.6 (7.6)\n\n\n4.x.x is the last version to support Python 2.7,\nand from the next major version (Celery 5.x) Python 3.6 or newer is required.\n\nIf you're running an older version of Python, you need to be running\nan older version of Celery:\n\n- Python 2.6: Celery series 3.1 or earlier.\n- Python 2.5: Celery series 3.0 or earlier.\n- Python 2.4 was Celery series 2.2 or earlier.\n\nCelery is a project with minimal funding,\nso we don't support Microsoft Windows.\nPlease don't open any issues related to that platform.\n\n*Celery* is usually used with a message broker to send and receive messages.\nThe RabbitMQ, Redis transports are feature complete,\nbut there's also experimental support for a myriad of other solutions, including\nusing SQLite for local development.\n\n*Celery* can run on a single machine, on multiple machines, or even\nacross datacenters.\n\nGet Started\n===========\n\nIf this is the first time you're trying to use Celery, or you're\nnew to Celery 4.4 coming from previous versions then you should read our\ngetting started tutorials:\n\n- `First steps with Celery`_\n\n Tutorial teaching you the bare minimum needed to get started with Celery.\n\n- `Next steps`_\n\n A more complete overview, showing more features.\n\n.. _`First steps with Celery`:\n http://docs.celeryproject.org/en/latest/getting-started/first-steps-with-celery.html\n\n.. _`Next steps`:\n http://docs.celeryproject.org/en/latest/getting-started/next-steps.html\n\nCelery is...\n=============\n\n- **Simple**\n\n Celery is easy to use and maintain, and does *not need configuration files*.\n\n It has an active, friendly community you can talk to for support,\n like at our `mailing-list`_, or the IRC channel.\n\n Here's one of the simplest applications you can make::\n\n from celery import Celery\n\n app = Celery('hello', broker='amqp://guest@localhost//')\n\n @app.task\n def hello():\n return 'hello world'\n\n- **Highly Available**\n\n Workers and clients will automatically retry in the event\n of connection loss or failure, and some brokers support\n HA in way of *Primary/Primary* or *Primary/Replica* replication.\n\n- **Fast**\n\n A single Celery process can process millions of tasks a minute,\n with sub-millisecond round-trip latency (using RabbitMQ,\n py-librabbitmq, and optimized settings).\n\n- **Flexible**\n\n Almost every part of *Celery* can be extended or used on its own,\n Custom pool implementations, serializers, compression schemes, logging,\n schedulers, consumers, producers, broker transports, and much more.\n\nIt supports...\n================\n\n - **Message Transports**\n\n - RabbitMQ_, Redis_, Amazon SQS\n\n - **Concurrency**\n\n - Prefork, Eventlet_, gevent_, single threaded (``solo``)\n\n - **Result Stores**\n\n - AMQP, Redis\n - memcached\n - SQLAlchemy, Django ORM\n - Apache Cassandra, IronCache, Elasticsearch\n\n - **Serialization**\n\n - *pickle*, *json*, *yaml*, *msgpack*.\n - *zlib*, *bzip2* compression.\n - Cryptographic message signing.\n\n.. _`Eventlet`: http://eventlet.net/\n.. _`gevent`: http://gevent.org/\n\n.. _RabbitMQ: https://rabbitmq.com\n.. _Redis: https://redis.io\n.. _SQLAlchemy: http://sqlalchemy.org\n\nFramework Integration\n=====================\n\nCelery is easy to integrate with web frameworks, some of which even have\nintegration packages:\n\n +--------------------+------------------------+\n | `Django`_ | not needed |\n +--------------------+------------------------+\n | `Pyramid`_ | `pyramid_celery`_ |\n +--------------------+------------------------+\n | `Pylons`_ | `celery-pylons`_ |\n +--------------------+------------------------+\n | `Flask`_ | not needed |\n +--------------------+------------------------+\n | `web2py`_ | `web2py-celery`_ |\n +--------------------+------------------------+\n | `Tornado`_ | `tornado-celery`_ |\n +--------------------+------------------------+\n\nThe integration packages aren't strictly necessary, but they can make\ndevelopment easier, and sometimes they add important hooks like closing\ndatabase connections at ``fork``.\n\n.. _`Django`: https://djangoproject.com/\n.. _`Pylons`: http://pylonsproject.org/\n.. _`Flask`: http://flask.pocoo.org/\n.. _`web2py`: http://web2py.com/\n.. _`Bottle`: https://bottlepy.org/\n.. _`Pyramid`: http://docs.pylonsproject.org/en/latest/docs/pyramid.html\n.. _`pyramid_celery`: https://pypi.org/project/pyramid_celery/\n.. _`celery-pylons`: https://pypi.org/project/celery-pylons/\n.. _`web2py-celery`: https://code.google.com/p/web2py-celery/\n.. _`Tornado`: http://www.tornadoweb.org/\n.. _`tornado-celery`: https://github.com/mher/tornado-celery/\n\n.. _celery-documentation:\n\nDocumentation\n=============\n\nThe `latest documentation`_ is hosted at Read The Docs, containing user guides,\ntutorials, and an API reference.\n\n\u6700\u65b0\u7684\u4e2d\u6587\u6587\u6863\u6258\u7ba1\u5728 https://www.celerycn.io/ \u4e2d\uff0c\u5305\u542b\u7528\u6237\u6307\u5357\u3001\u6559\u7a0b\u3001API\u63a5\u53e3\u7b49\u3002\n\n.. _`latest documentation`: http://docs.celeryproject.org/en/latest/\n\n.. _celery-installation:\n\nInstallation\n============\n\nYou can install Celery either via the Python Package Index (PyPI)\nor from source.\n\nTo install using ``pip``:\n\n::\n\n\n $ pip install -U Celery\n\n.. _bundles:\n\nBundles\n-------\n\nCelery also defines a group of bundles that can be used\nto install Celery and the dependencies for a given feature.\n\nYou can specify these in your requirements or on the ``pip``\ncommand-line by using brackets. Multiple bundles can be specified by\nseparating them by commas.\n\n::\n\n\n $ pip install \"celery[librabbitmq]\"\n\n $ pip install \"celery[librabbitmq,redis,auth,msgpack]\"\n\nThe following bundles are available:\n\nSerializers\n~~~~~~~~~~~\n\n:``celery[auth]``:\n for using the ``auth`` security serializer.\n\n:``celery[msgpack]``:\n for using the msgpack serializer.\n\n:``celery[yaml]``:\n for using the yaml serializer.\n\nConcurrency\n~~~~~~~~~~~\n\n:``celery[eventlet]``:\n for using the ``eventlet`` pool.\n\n:``celery[gevent]``:\n for using the ``gevent`` pool.\n\nTransports and Backends\n~~~~~~~~~~~~~~~~~~~~~~~\n\n:``celery[librabbitmq]``:\n for using the librabbitmq C library.\n\n:``celery[redis]``:\n for using Redis as a message transport or as a result backend.\n\n:``celery[sqs]``:\n for using Amazon SQS as a message transport.\n\n:``celery[tblib``]:\n for using the ``task_remote_tracebacks`` feature.\n\n:``celery[memcache]``:\n for using Memcached as a result backend (using ``pylibmc``)\n\n:``celery[pymemcache]``:\n for using Memcached as a result backend (pure-Python implementation).\n\n:``celery[cassandra]``:\n for using Apache Cassandra as a result backend with DataStax driver.\n\n:``celery[azureblockblob]``:\n for using Azure Storage as a result backend (using ``azure-storage``)\n\n:``celery[s3]``:\n for using S3 Storage as a result backend.\n\n:``celery[couchbase]``:\n for using Couchbase as a result backend.\n\n:``celery[arangodb]``:\n for using ArangoDB as a result backend.\n\n:``celery[elasticsearch]``:\n for using Elasticsearch as a result backend.\n\n:``celery[riak]``:\n for using Riak as a result backend.\n\n:``celery[cosmosdbsql]``:\n for using Azure Cosmos DB as a result backend (using ``pydocumentdb``)\n\n:``celery[zookeeper]``:\n for using Zookeeper as a message transport.\n\n:``celery[sqlalchemy]``:\n for using SQLAlchemy as a result backend (*supported*).\n\n:``celery[pyro]``:\n for using the Pyro4 message transport (*experimental*).\n\n:``celery[slmq]``:\n for using the SoftLayer Message Queue transport (*experimental*).\n\n:``celery[consul]``:\n for using the Consul.io Key/Value store as a message transport or result backend (*experimental*).\n\n:``celery[django]``:\n specifies the lowest version possible for Django support.\n\n You should probably not use this in your requirements, it's here\n for informational purposes only.\n\n\n.. _celery-installing-from-source:\n\nDownloading and installing from source\n--------------------------------------\n\nDownload the latest version of Celery from PyPI:\n\nhttps://pypi.org/project/celery/\n\nYou can install it by doing the following,:\n\n::\n\n\n $ tar xvfz celery-0.0.0.tar.gz\n $ cd celery-0.0.0\n $ python setup.py build\n # python setup.py install\n\nThe last command must be executed as a privileged user if\nyou aren't currently using a virtualenv.\n\n.. _celery-installing-from-git:\n\nUsing the development version\n-----------------------------\n\nWith pip\n~~~~~~~~\n\nThe Celery development version also requires the development\nversions of ``kombu``, ``amqp``, ``billiard``, and ``vine``.\n\nYou can install the latest snapshot of these using the following\npip commands:\n\n::\n\n\n $ pip install https://github.com/celery/celery/zipball/master#egg=celery\n $ pip install https://github.com/celery/billiard/zipball/master#egg=billiard\n $ pip install https://github.com/celery/py-amqp/zipball/master#egg=amqp\n $ pip install https://github.com/celery/kombu/zipball/master#egg=kombu\n $ pip install https://github.com/celery/vine/zipball/master#egg=vine\n\nWith git\n~~~~~~~~\n\nPlease see the Contributing section.\n\n.. _getting-help:\n\nGetting Help\n============\n\n.. _mailing-list:\n\nMailing list\n------------\n\nFor discussions about the usage, development, and future of Celery,\nplease join the `celery-users`_ mailing list.\n\n.. _`celery-users`: https://groups.google.com/group/celery-users/\n\n.. _irc-channel:\n\nIRC\n---\n\nCome chat with us on IRC. The **#celery** channel is located at the `Freenode`_\nnetwork.\n\n.. _`Freenode`: https://freenode.net\n\n.. _bug-tracker:\n\nBug tracker\n===========\n\nIf you have any suggestions, bug reports, or annoyances please report them\nto our issue tracker at https://github.com/celery/celery/issues/\n\n.. _wiki:\n\nWiki\n====\n\nhttps://github.com/celery/celery/wiki\n\nCredits\n=======\n\n.. _contributing-short:\n\nContributors\n------------\n\nThis project exists thanks to all the people who contribute. Development of\n`celery` happens at GitHub: https://github.com/celery/celery\n\nYou're highly encouraged to participate in the development\nof `celery`. If you don't like GitHub (for some reason) you're welcome\nto send regular patches.\n\nBe sure to also read the `Contributing to Celery`_ section in the\ndocumentation.\n\n.. _`Contributing to Celery`:\n http://docs.celeryproject.org/en/master/contributing.html\n\n|oc-contributors|\n\n.. |oc-contributors| image:: https://opencollective.com/celery/contributors.svg?width=890&button=false\n :target: https://github.com/celery/celery/graphs/contributors\n\nBackers\n-------\n\nThank you to all our backers! \ud83d\ude4f [`Become a backer`_]\n\n.. _`Become a backer`: https://opencollective.com/celery#backer\n\n|oc-backers|\n\n.. |oc-backers| image:: https://opencollective.com/celery/backers.svg?width=890\n :target: https://opencollective.com/celery#backers\n\nSponsors\n--------\n\nSupport this project by becoming a sponsor. Your logo will show up here with a\nlink to your website. [`Become a sponsor`_]\n\n.. _`Become a sponsor`: https://opencollective.com/celery#sponsor\n\n|oc-sponsors|\n\n.. |oc-sponsors| image:: https://opencollective.com/celery/sponsor/0/avatar.svg\n :target: https://opencollective.com/celery/sponsor/0/website\n\n.. _license:\n\nLicense\n=======\n\nThis software is licensed under the `New BSD License`. See the ``LICENSE``\nfile in the top distribution directory for the full license text.\n\n.. # vim: syntax=rst expandtab tabstop=4 shiftwidth=4 shiftround\n\n.. |build-status| image:: https://secure.travis-ci.org/celery/celery.png?branch=master\n :alt: Build status\n :target: https://travis-ci.org/celery/celery\n\n.. |coverage| image:: https://codecov.io/github/celery/celery/coverage.svg?branch=master\n :target: https://codecov.io/github/celery/celery?branch=master\n\n.. |license| image:: https://img.shields.io/pypi/l/celery.svg\n :alt: BSD License\n :target: https://opensource.org/licenses/BSD-3-Clause\n\n.. |wheel| image:: https://img.shields.io/pypi/wheel/celery.svg\n :alt: Celery can be installed via wheel\n :target: https://pypi.org/project/celery/\n\n.. |pyversion| image:: https://img.shields.io/pypi/pyversions/celery.svg\n :alt: Supported Python versions.\n :target: https://pypi.org/project/celery/\n\n.. |pyimp| image:: https://img.shields.io/pypi/implementation/celery.svg\n :alt: Support Python implementations.\n :target: https://pypi.org/project/celery/\n\n.. |ocbackerbadge| image:: https://opencollective.com/celery/backers/badge.svg\n :alt: Backers on Open Collective\n :target: #backers\n\n.. |ocsponsorbadge| image:: https://opencollective.com/celery/sponsors/badge.svg\n :alt: Sponsors on Open Collective\n :target: #sponsors\n\n.. |downloads| image:: https://pepy.tech/badge/celery\n :alt: Downloads\n :target: https://pepy.tech/project/celery\n\n\n",
+ "description_content_type":"",
+ "docs_url":"https://pythonhosted.org/celery/",
+ "download_url":"",
+ "downloads":{
+ "last_day":-1,
+ "last_month":-1,
+ "last_week":-1
+ },
+ "home_page":"http://celeryproject.org",
+ "keywords":"task job queue distributed messaging actor",
+ "license":"BSD",
+ "maintainer":"",
+ "maintainer_email":"",
+ "name":"celery",
+ "package_url":"https://pypi.org/project/celery/",
+ "platform":"any",
+ "project_url":"https://pypi.org/project/celery/",
+ "project_urls":{
+ "Homepage":"http://celeryproject.org"
+ },
+ "release_url":"https://pypi.org/project/celery/4.4.0/",
+ "requires_dist":[
+ "pytz (>dev)",
+ "billiard (<4.0,>=3.6.1)",
+ "kombu (<4.7,>=4.6.7)",
+ "vine (==1.3.0)",
+ "pyArango (>=1.3.2) ; extra == 'arangodb'",
+ "cryptography ; extra == 'auth'",
+ "azure-storage (==0.36.0) ; extra == 'azureblockblob'",
+ "azure-common (==1.1.5) ; extra == 'azureblockblob'",
+ "azure-storage-common (==1.1.0) ; extra == 'azureblockblob'",
+ "brotli (>=1.0.0) ; (platform_python_implementation == \"CPython\") and extra == 'brotli'",
+ "brotlipy (>=0.7.0) ; (platform_python_implementation == \"PyPy\") and extra == 'brotli'",
+ "cassandra-driver ; extra == 'cassandra'",
+ "python-consul ; extra == 'consul'",
+ "pydocumentdb (==2.3.2) ; extra == 'cosmosdbsql'",
+ "couchbase ; extra == 'couchbase'",
+ "couchbase-cffi ; (platform_python_implementation == \"PyPy\") and extra == 'couchbase'",
+ "pycouchdb ; extra == 'couchdb'",
+ "Django (>=1.11) ; extra == 'django'",
+ "boto3 (>=1.9.178) ; extra == 'dynamodb'",
+ "elasticsearch ; extra == 'elasticsearch'",
+ "eventlet (>=0.24.1) ; extra == 'eventlet'",
+ "gevent ; extra == 'gevent'",
+ "librabbitmq (>=1.5.0) ; extra == 'librabbitmq'",
+ "backports.lzma ; (python_version < \"3.3\") and extra == 'lzma'",
+ "pylibmc ; extra == 'memcache'",
+ "pymongo[srv] (>=3.3.0) ; extra == 'mongodb'",
+ "msgpack ; extra == 'msgpack'",
+ "python-memcached ; extra == 'pymemcache'",
+ "pyro4 ; extra == 'pyro'",
+ "redis (>=3.2.0) ; extra == 'redis'",
+ "riak (>=2.0) ; extra == 'riak'",
+ "boto3 (>=1.9.125) ; extra == 's3'",
+ "softlayer-messaging (>=1.0.3) ; extra == 'slmq'",
+ "ephem ; extra == 'solar'",
+ "sqlalchemy ; extra == 'sqlalchemy'",
+ "boto3 (>=1.9.125) ; extra == 'sqs'",
+ "pycurl ; extra == 'sqs'",
+ "tblib (>=1.3.0) ; (python_version < \"3.8.0\") and extra == 'tblib'",
+ "tblib (>=1.5.0) ; (python_version >= \"3.8.0\") and extra == 'tblib'",
+ "PyYAML (>=3.10) ; extra == 'yaml'",
+ "kazoo (>=1.3.1) ; extra == 'zookeeper'",
+ "zstandard ; extra == 'zstd'"
+ ],
+ "requires_python":">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*,",
+ "summary":"Distributed Task Queue.",
+ "version":"4.4.0"
+ },
+ "last_serial":6308640,
+ "releases":{
+ "0.1.10":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"f014724574211a4388fc0f2f2030cbf3",
+ "sha256":"97cf6609f6f1d4feef90694acba84cd36f1ed0442615d1f9e603a7dab042f1d5"
+ },
+ "downloads":-1,
+ "filename":"celery-0.1.10.tar.gz",
+ "has_sig":false,
+ "md5_digest":"f014724574211a4388fc0f2f2030cbf3",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":58005,
+ "upload_time":"2009-05-11T12:53:20",
+ "upload_time_iso_8601":"2009-05-11T12:53:20.521919Z",
+ "url":"https://files.pythonhosted.org/packages/e4/c5/91b850759f576123085a3a60ee8356ce477ee467dbbf9ff6eec458e2237a/celery-0.1.10.tar.gz"
+ }
+ ],
+ "0.1.11":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"67b7bd27c0412e4360eaed115aa46d1f",
+ "sha256":"7e281e3401acbd61328badf5c4b6f6a5cc00b9fd06733377754f3e29777aa23e"
+ },
+ "downloads":-1,
+ "filename":"celery-0.1.11.tar.gz",
+ "has_sig":false,
+ "md5_digest":"67b7bd27c0412e4360eaed115aa46d1f",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":53134,
+ "upload_time":"2009-05-12T14:11:57",
+ "upload_time_iso_8601":"2009-05-12T14:11:57.536352Z",
+ "url":"https://files.pythonhosted.org/packages/fa/08/66b08efbe6e31e3bd7a235dab39aeafef2229dc4ccd1aaf48aaa4aa1952c/celery-0.1.11.tar.gz"
+ }
+ ],
+ "0.1.12":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"ce560d3dac3b92bd01bb2bf39e69e0c5",
+ "sha256":"0ebf4d5f61452c50c8601c550a579a25d41ca447f3a1ebc59e4d2e59b24ae23e"
+ },
+ "downloads":-1,
+ "filename":"celery-0.1.12.tar.gz",
+ "has_sig":false,
+ "md5_digest":"ce560d3dac3b92bd01bb2bf39e69e0c5",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":45502,
+ "upload_time":"2009-05-18T16:48:01",
+ "upload_time_iso_8601":"2009-05-18T16:48:01.569477Z",
+ "url":"https://files.pythonhosted.org/packages/01/ef/e63cda3896838b4231b73dac84213c7c559b30fbeb60dcc84d58f13b0f65/celery-0.1.12.tar.gz"
+ }
+ ],
+ "0.1.13":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"7be6b0a2350055a5a39ad9d004dc0b19",
+ "sha256":"a8aa3d1c873ef6e2fcf0a1a4a1343360fadb76b6273c2097d1778c3308df7802"
+ },
+ "downloads":-1,
+ "filename":"celery-0.1.13.tar.gz",
+ "has_sig":false,
+ "md5_digest":"7be6b0a2350055a5a39ad9d004dc0b19",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":245409,
+ "upload_time":"2009-05-19T12:52:16",
+ "upload_time_iso_8601":"2009-05-19T12:52:16.159662Z",
+ "url":"https://files.pythonhosted.org/packages/2c/40/b042ab9a23fe862f0243af651552a76d656c8f8c6593fb683e94758b07ae/celery-0.1.13.tar.gz"
+ }
+ ],
+ "0.1.14":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"9fccaba71ef42dc60a9b96b450e84280",
+ "sha256":"f5a98b8a64916990abab043a551b9bb9155611b9bf0227389a02f76b699d3cf1"
+ },
+ "downloads":-1,
+ "filename":"celery-0.1.14.tar.gz",
+ "has_sig":false,
+ "md5_digest":"9fccaba71ef42dc60a9b96b450e84280",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":245230,
+ "upload_time":"2009-05-19T13:10:10",
+ "upload_time_iso_8601":"2009-05-19T13:10:10.373285Z",
+ "url":"https://files.pythonhosted.org/packages/e8/d0/b3c2b77335f0d77661412d0fc3d7ee5ba268a7791cd614ff09a5737de93e/celery-0.1.14.tar.gz"
+ }
+ ],
+ "0.1.15":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"a69642c5a741c575a7df6219008708b1",
+ "sha256":"c10bf64919d95501dbebd6bbd780ad06e150141522b1ac75d42669e390cbb3ab"
+ },
+ "downloads":-1,
+ "filename":"celery-0.1.15.tar.gz",
+ "has_sig":false,
+ "md5_digest":"a69642c5a741c575a7df6219008708b1",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":276842,
+ "upload_time":"2009-05-19T16:21:07",
+ "upload_time_iso_8601":"2009-05-19T16:21:07.650308Z",
+ "url":"https://files.pythonhosted.org/packages/94/98/361d09b0042f22c2eae96e41516d0bb7675f2dcb2f0906e0c87b4496d7d0/celery-0.1.15.tar.gz"
+ }
+ ],
+ "0.1.2":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"a63df9f3ce1883b90fdcd18df4ae79f7",
+ "sha256":"bc1d99ede8e9525b121029d724282dcda5191220a946f4695c7ad371f2c0561a"
+ },
+ "downloads":-1,
+ "filename":"celery-0.1.2.tar.gz",
+ "has_sig":false,
+ "md5_digest":"a63df9f3ce1883b90fdcd18df4ae79f7",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":11383,
+ "upload_time":"2009-04-27T12:49:20",
+ "upload_time_iso_8601":"2009-04-27T12:49:20.215689Z",
+ "url":"https://files.pythonhosted.org/packages/c9/b7/4ea5dba86291f3c04c54b90388b39fa22cf55010cb93ca57f25b978987e0/celery-0.1.2.tar.gz"
+ }
+ ],
+ "0.1.4":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"0eeae544975b5a51d7c12f2156fc17f1",
+ "sha256":"380e4d4c0cafb3f5f9a365639571b105284258293bdce92fc9049806929ad307"
+ },
+ "downloads":-1,
+ "filename":"celery-0.1.4.tar.gz",
+ "has_sig":false,
+ "md5_digest":"0eeae544975b5a51d7c12f2156fc17f1",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":12873,
+ "upload_time":"2009-04-27T16:25:42",
+ "upload_time_iso_8601":"2009-04-27T16:25:42.898129Z",
+ "url":"https://files.pythonhosted.org/packages/c5/bd/b6d02275036d749ed04eeca6fa4791f8da0c12364ac534f50cf4cb0f67d0/celery-0.1.4.tar.gz"
+ }
+ ],
+ "0.1.6":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"a037f7f1f4319efdeb8dea2872c07716",
+ "sha256":"3ea2ee74edb5071749855eba66316e3c080668eaac682db3199a0cc3318e27fc"
+ },
+ "downloads":-1,
+ "filename":"celery-0.1.6.tar.gz",
+ "has_sig":false,
+ "md5_digest":"a037f7f1f4319efdeb8dea2872c07716",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":29537,
+ "upload_time":"2009-04-29T16:50:02",
+ "upload_time_iso_8601":"2009-04-29T16:50:02.322478Z",
+ "url":"https://files.pythonhosted.org/packages/c1/6b/2adaf75ea00d95e1acc6a669b8cec3e5d8de8152b942dd59888099b8a5bf/celery-0.1.6.tar.gz"
+ }
+ ],
+ "0.1.7":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"8a8c0444e3e7b23b01c703db1ff74e19",
+ "sha256":"ee8b7ae0d974b2db1af1d2415e2441f1862284c9335e57b699be10228e0018e7"
+ },
+ "downloads":-1,
+ "filename":"celery-0.1.7.tar.gz",
+ "has_sig":false,
+ "md5_digest":"8a8c0444e3e7b23b01c703db1ff74e19",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":32059,
+ "upload_time":"2009-04-30T14:32:02",
+ "upload_time_iso_8601":"2009-04-30T14:32:02.607127Z",
+ "url":"https://files.pythonhosted.org/packages/65/41/2ec777848ba6ba6d255f8f618bb5f7dba7401d40fc8cbca6ecc714ebd6e8/celery-0.1.7.tar.gz"
+ }
+ ],
+ "0.1.8":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"aad8ea8df4c7b7b05aad7c37f6b12e26",
+ "sha256":"7a297c58c1f9e40358d788238bb316b7c668ccda7c9bb5f6b933dd19c7eaf0bb"
+ },
+ "downloads":-1,
+ "filename":"celery-0.1.8.tar.gz",
+ "has_sig":false,
+ "md5_digest":"aad8ea8df4c7b7b05aad7c37f6b12e26",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":50456,
+ "upload_time":"2009-05-07T12:30:48",
+ "upload_time_iso_8601":"2009-05-07T12:30:48.181182Z",
+ "url":"https://files.pythonhosted.org/packages/5f/07/e57c2365cba307801a3b44d40c773297f2ee7c9f7f0b9a22db66d53e88da/celery-0.1.8.tar.gz"
+ }
+ ],
+ "0.2.0":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"16e8e984153d898e6a2841d2b904fb0c",
+ "sha256":"aff01560ddc41099de467fdfb71147fbcb44a8a36ba77636c3316e6c5c1c0917"
+ },
+ "downloads":-1,
+ "filename":"celery-0.2.0.tar.gz",
+ "has_sig":false,
+ "md5_digest":"16e8e984153d898e6a2841d2b904fb0c",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":374824,
+ "upload_time":"2009-05-27T18:19:48",
+ "upload_time_iso_8601":"2009-05-27T18:19:48.085180Z",
+ "url":"https://files.pythonhosted.org/packages/0a/8b/b533a83bf19fdaab487a7f1b2cd11f546336858e321292be7b56b8f2375e/celery-0.2.0.tar.gz"
+ }
+ ],
+ "0.3.0":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"16a76c204f3cf5f3c37281fa1007d084",
+ "sha256":"a1c8623921dc89bdf39db9cba4d3b3641e058d20ae9ae8ffde7b67dc9b3d81f2"
+ },
+ "downloads":-1,
+ "filename":"celery-0.3.0.tar.gz",
+ "has_sig":false,
+ "md5_digest":"16a76c204f3cf5f3c37281fa1007d084",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":427156,
+ "upload_time":"2009-06-08T18:05:54",
+ "upload_time_iso_8601":"2009-06-08T18:05:54.025526Z",
+ "url":"https://files.pythonhosted.org/packages/3c/00/d4786a6a1bde4138292cb46e4f76e6964610cdf2032eb5e7cdc59ad0bfb4/celery-0.3.0.tar.gz"
+ }
+ ],
+ "0.3.20":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"2a00ad8c98e47f2be80197834e611a43",
+ "sha256":"69f5c8c5b80053069b087d66056883c2b6cadad479776020eb20343f2b01f29a"
+ },
+ "downloads":-1,
+ "filename":"celery-0.3.20.tar.gz",
+ "has_sig":false,
+ "md5_digest":"2a00ad8c98e47f2be80197834e611a43",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":437683,
+ "upload_time":"2009-06-25T20:53:37",
+ "upload_time_iso_8601":"2009-06-25T20:53:37.474499Z",
+ "url":"https://files.pythonhosted.org/packages/31/82/ff63b78e39221ff0303eef2a870d290349a72f00d36c660ebe6fd82b3d8a/celery-0.3.20.tar.gz"
+ }
+ ],
+ "0.3.7":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"4142a4b09e37f7ecd0cb199c137fe882",
+ "sha256":"d0797a1e31039f55a08f6f67f4cc0e0c9c32f987fd0dee93666c6f132aff4e0d"
+ },
+ "downloads":-1,
+ "filename":"celery-0.3.7.tar.gz",
+ "has_sig":false,
+ "md5_digest":"4142a4b09e37f7ecd0cb199c137fe882",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":455872,
+ "upload_time":"2009-06-16T23:48:03",
+ "upload_time_iso_8601":"2009-06-16T23:48:03.750483Z",
+ "url":"https://files.pythonhosted.org/packages/07/32/977a11aab74ffe369a73be38bcfb6a209e3fdbff59efb7bc4993b396f5ab/celery-0.3.7.tar.gz"
+ }
+ ],
+ "0.4.0":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"e55043f5abd461b66dd05fe605d39884",
+ "sha256":"0a48b662542dedb3576e5d413927e2a4d92c188aa043eb8fffa5e941ae87ea2b"
+ },
+ "downloads":-1,
+ "filename":"celery-0.4.0.tar.gz",
+ "has_sig":false,
+ "md5_digest":"e55043f5abd461b66dd05fe605d39884",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":448254,
+ "upload_time":"2009-07-01T19:42:42",
+ "upload_time_iso_8601":"2009-07-01T19:42:42.599194Z",
+ "url":"https://files.pythonhosted.org/packages/c9/43/4a38e3082fa78cfbbcef6f4e50661689f97bf15da1923fdaad915888347b/celery-0.4.0.tar.gz"
+ }
+ ],
+ "0.4.1":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"e2dbd6d28f7636e088ef77b6df54b82c",
+ "sha256":"38669031b8164a413f80def985a40bee57d7cc39915a7298090c50652b240d47"
+ },
+ "downloads":-1,
+ "filename":"celery-0.4.1.tar.gz",
+ "has_sig":false,
+ "md5_digest":"e2dbd6d28f7636e088ef77b6df54b82c",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":448418,
+ "upload_time":"2009-07-02T14:09:41",
+ "upload_time_iso_8601":"2009-07-02T14:09:41.127082Z",
+ "url":"https://files.pythonhosted.org/packages/7c/30/d0b0912934c447ffcee595cc80fc5eb60ef412474dc22635756e10671fcd/celery-0.4.1.tar.gz"
+ }
+ ],
+ "0.6.0":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"0545f89033e1639bbb1be0974465577c",
+ "sha256":"6ac5e64af23000a7a1a4645850b064698b025561b090c0c331542bcd9270576b"
+ },
+ "downloads":-1,
+ "filename":"celery-0.6.0.tar.gz",
+ "has_sig":false,
+ "md5_digest":"0545f89033e1639bbb1be0974465577c",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":460242,
+ "upload_time":"2009-08-07T11:32:02",
+ "upload_time_iso_8601":"2009-08-07T11:32:02.598345Z",
+ "url":"https://files.pythonhosted.org/packages/ab/f0/b716dcd55d8e70b26b26836a2c12e03a0eee2804c261daf1b8801f88a7ff/celery-0.6.0.tar.gz"
+ }
+ ],
+ "0.8.0":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"a98604e9ce736026f4dee88000146d99",
+ "sha256":"6a8cb2cd10689cc9b5a33f15d3479471b5c689e31e74432c7db75f7dd4c3a3ef"
+ },
+ "downloads":-1,
+ "filename":"celery-0.8.0.tar.gz",
+ "has_sig":false,
+ "md5_digest":"a98604e9ce736026f4dee88000146d99",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":489924,
+ "upload_time":"2009-09-22T15:07:52",
+ "upload_time_iso_8601":"2009-09-22T15:07:52.052163Z",
+ "url":"https://files.pythonhosted.org/packages/0e/7c/027ffc99fe53a21dd90f536e0e8353d997a1e1b10061cb0c8a4371846dad/celery-0.8.0.tar.gz"
+ }
+ ],
+ "0.8.1":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"65738c5afe9c92ee38654deaee583289",
+ "sha256":"ed3e9ade5599cf4744c854bceeadc0c081363765aa20b130414d0478aed93374"
+ },
+ "downloads":-1,
+ "filename":"celery-0.8.1.tar.gz",
+ "has_sig":false,
+ "md5_digest":"65738c5afe9c92ee38654deaee583289",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":739072,
+ "upload_time":"2009-11-17T15:29:43",
+ "upload_time_iso_8601":"2009-11-17T15:29:43.629153Z",
+ "url":"https://files.pythonhosted.org/packages/93/e0/e82b8a220cb6715958ab0f7f425ffa8ca26a46f4a89ace326973a59156c3/celery-0.8.1.tar.gz"
+ }
+ ],
+ "0.8.2":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"1d434f9a3a69f8200196b00f69fa5bb0",
+ "sha256":"373fdafdb4c02a67bde9012ed74df7495e458919b09c895e78ec420437ab00fb"
+ },
+ "downloads":-1,
+ "filename":"celery-0.8.2.tar.gz",
+ "has_sig":false,
+ "md5_digest":"1d434f9a3a69f8200196b00f69fa5bb0",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":735863,
+ "upload_time":"2009-11-20T15:45:22",
+ "upload_time_iso_8601":"2009-11-20T15:45:22.002794Z",
+ "url":"https://files.pythonhosted.org/packages/2f/ca/a2a748e4827e7709717bc6fca7be018a4cb61e877d5ed41050c0476d5d72/celery-0.8.2.tar.gz"
+ }
+ ],
+ "0.8.3":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"0d7f6f9a2bbe15d6f93e037ecf67d54a",
+ "sha256":"c396f638c71e3fa5fe7fdd7369852ce3da3752fee2ad901700a878c8fbe88be2"
+ },
+ "downloads":-1,
+ "filename":"celery-0.8.3.tar.gz",
+ "has_sig":false,
+ "md5_digest":"0d7f6f9a2bbe15d6f93e037ecf67d54a",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":733046,
+ "upload_time":"2009-12-22T09:45:41",
+ "upload_time_iso_8601":"2009-12-22T09:45:41.806687Z",
+ "url":"https://files.pythonhosted.org/packages/36/08/5e99b4510e35de3ccf8897e42f06578dafba77a35f7b324158d0a880fa54/celery-0.8.3.tar.gz"
+ }
+ ],
+ "0.8.4":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"953a0cacf3b5d8de94348d3ed958122e",
+ "sha256":"4d28623b98677d781cc6a0212b9e199f86a257571eaa52d0aafa9f87b3d626b0"
+ },
+ "downloads":-1,
+ "filename":"celery-0.8.4.tar.gz",
+ "has_sig":false,
+ "md5_digest":"953a0cacf3b5d8de94348d3ed958122e",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":733355,
+ "upload_time":"2010-02-05T13:57:40",
+ "upload_time_iso_8601":"2010-02-05T13:57:40.634120Z",
+ "url":"https://files.pythonhosted.org/packages/c5/5a/69213c88917f99d526fed81438ffeaafeb3aeb539de3c670b331e698dbcc/celery-0.8.4.tar.gz"
+ }
+ ],
+ "1.0.0":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"0e711cb074eff8ef205ef1274b30e8ad",
+ "sha256":"41eba3baf263be8d24a15e37a27cee8af524edced04ceacb38d0e4121f47a0c6"
+ },
+ "downloads":-1,
+ "filename":"celery-1.0.0.tar.gz",
+ "has_sig":false,
+ "md5_digest":"0e711cb074eff8ef205ef1274b30e8ad",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1462227,
+ "upload_time":"2010-02-10T16:01:07",
+ "upload_time_iso_8601":"2010-02-10T16:01:07.281364Z",
+ "url":"https://files.pythonhosted.org/packages/07/2a/4f5bc54e1cd7fba16b84f0b6b9e187956a607a9dffe8003a15852b1a465c/celery-1.0.0.tar.gz"
+ }
+ ],
+ "1.0.1":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"164ab6192d7513f5a098b735a6b42afc",
+ "sha256":"0993d9f0e7a3544dcdd92f4fdc83374fa11e8d7d1c06c96ac932264b368e32e7"
+ },
+ "downloads":-1,
+ "filename":"celery-1.0.1.tar.gz",
+ "has_sig":false,
+ "md5_digest":"164ab6192d7513f5a098b735a6b42afc",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1482530,
+ "upload_time":"2010-03-20T19:05:08",
+ "upload_time_iso_8601":"2010-03-20T19:05:08.467055Z",
+ "url":"https://files.pythonhosted.org/packages/c7/f5/205c192eb466811ad06b2ae314265324d3e37b77403e28152a62f8e54f5d/celery-1.0.1.tar.gz"
+ }
+ ],
+ "1.0.2":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"927b8999d928784b062c13994f88e130",
+ "sha256":"b8699481b3dbe75e1fbe89ff3e0eacb74de135dfe830dd2747b99fa0ebd4e0b8"
+ },
+ "downloads":-1,
+ "filename":"celery-1.0.2.tar.gz",
+ "has_sig":false,
+ "md5_digest":"927b8999d928784b062c13994f88e130",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1485539,
+ "upload_time":"2010-03-31T13:29:12",
+ "upload_time_iso_8601":"2010-03-31T13:29:12.671889Z",
+ "url":"https://files.pythonhosted.org/packages/15/b3/d2975f3ce803a40997a73dd73a07c9a0a0012c02581a8f562f1b950cb1ca/celery-1.0.2.tar.gz"
+ }
+ ],
+ "1.0.3":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"b01092e6112137f7d2b403f5cd16133e",
+ "sha256":"3b586331ce7a9ea51a018988072ef59e293550a5733e818f0d522ec0df54a8e0"
+ },
+ "downloads":-1,
+ "filename":"celery-1.0.3.tar.gz",
+ "has_sig":false,
+ "md5_digest":"b01092e6112137f7d2b403f5cd16133e",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1496971,
+ "upload_time":"2010-05-15T15:28:22",
+ "upload_time_iso_8601":"2010-05-15T15:28:22.255769Z",
+ "url":"https://files.pythonhosted.org/packages/af/8f/4b4527b523bf18eb7ac6d8a490ff51df60c0e52baf8e37796e3da73e0609/celery-1.0.3.tar.gz"
+ }
+ ],
+ "1.0.4":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"7ba41bbf305e7677a26162704ebb9327",
+ "sha256":"98e72b7014f40fdea79a70db800b502658f79b8e77b2ebb9ab1cbf94c1d9c8de"
+ },
+ "downloads":-1,
+ "filename":"celery-1.0.4.tar.gz",
+ "has_sig":false,
+ "md5_digest":"7ba41bbf305e7677a26162704ebb9327",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1502398,
+ "upload_time":"2010-05-31T11:01:25",
+ "upload_time_iso_8601":"2010-05-31T11:01:25.629724Z",
+ "url":"https://files.pythonhosted.org/packages/11/67/482f346d8ac04154a4575d8daf1e1f25d10d62a33f61902e272cc5809d8b/celery-1.0.4.tar.gz"
+ }
+ ],
+ "1.0.5":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"c93f7522c2ce98a32e1cc1a970a7dba1",
+ "sha256":"70494f0b31c3e54663a6164371ec04c0b08c50bee8f97d173a574ad492d408eb"
+ },
+ "downloads":-1,
+ "filename":"celery-1.0.5.tar.gz",
+ "has_sig":false,
+ "md5_digest":"c93f7522c2ce98a32e1cc1a970a7dba1",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1507642,
+ "upload_time":"2010-06-01T15:00:23",
+ "upload_time_iso_8601":"2010-06-01T15:00:23.378370Z",
+ "url":"https://files.pythonhosted.org/packages/a2/10/f51deedda46be3051d5db96905a2835264ff8022b2f20b8fae67a326d163/celery-1.0.5.tar.gz"
+ }
+ ],
+ "1.0.6":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"88ae6a25b0f63b79a9a654b8694a93c6",
+ "sha256":"eda05043686b3c554c66112ceabca79e0f162467afefaf951671510491c59071"
+ },
+ "downloads":-1,
+ "filename":"celery-1.0.6.tar.gz",
+ "has_sig":false,
+ "md5_digest":"88ae6a25b0f63b79a9a654b8694a93c6",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1502650,
+ "upload_time":"2010-06-30T10:03:18",
+ "upload_time_iso_8601":"2010-06-30T10:03:18.768517Z",
+ "url":"https://files.pythonhosted.org/packages/97/d8/5b798239afd16b5712ea360698ca6bbffd28214947d36eb125b49e341e17/celery-1.0.6.tar.gz"
+ }
+ ],
+ "2.0.0":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"b9b14d1092a10f6436435b27cd7a15f9",
+ "sha256":"9e7340aaec3926d90f78e4bc96175b6deb6b50367c5de978955ca6cabf85e2dd"
+ },
+ "downloads":-1,
+ "filename":"celery-2.0.0.tar.gz",
+ "has_sig":false,
+ "md5_digest":"b9b14d1092a10f6436435b27cd7a15f9",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1561868,
+ "upload_time":"2010-07-02T14:50:39",
+ "upload_time_iso_8601":"2010-07-02T14:50:39.629604Z",
+ "url":"https://files.pythonhosted.org/packages/9c/c9/f69b9915c62f4105383834180e1c4a7ff36da1cf90608a939ee578173879/celery-2.0.0.tar.gz"
+ }
+ ],
+ "2.0.1":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"b5b523890ea22281ee2dff6a0767abb8",
+ "sha256":"336bba335cf7c79a7c5d4e692f7d84fa80f5b0cbb56ceda61ee70408c071b046"
+ },
+ "downloads":-1,
+ "filename":"celery-2.0.1.tar.gz",
+ "has_sig":false,
+ "md5_digest":"b5b523890ea22281ee2dff6a0767abb8",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1071118,
+ "upload_time":"2010-07-09T15:41:41",
+ "upload_time_iso_8601":"2010-07-09T15:41:41.150547Z",
+ "url":"https://files.pythonhosted.org/packages/72/53/247ab78e12f2b8c2fc7a4740779167dff9791c86230ca657a5fa7bbffd0a/celery-2.0.1.tar.gz"
+ }
+ ],
+ "2.0.2":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"b0e3aa6a4df49bacd45305bc9ab8f9ae",
+ "sha256":"e4171d41a4c63ae639c0c7b1c00a6e361f97ce04d5d0ede3165723b62e440e28"
+ },
+ "downloads":-1,
+ "filename":"celery-2.0.2.tar.gz",
+ "has_sig":false,
+ "md5_digest":"b0e3aa6a4df49bacd45305bc9ab8f9ae",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1078142,
+ "upload_time":"2010-07-23T23:23:23",
+ "upload_time_iso_8601":"2010-07-23T23:23:23.525795Z",
+ "url":"https://files.pythonhosted.org/packages/3e/da/591df660751e72c8456d149f1593acb1ed40eb01c9d9f2799d2a5f8e34f3/celery-2.0.2.tar.gz"
+ }
+ ],
+ "2.0.3":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"824e934e56e5e4ac2d5b8bbe6eba8c50",
+ "sha256":"078ba7affd258df1eead635b1ed378da25af0aaa002d63ba9ba8f2e290cc7e30"
+ },
+ "downloads":-1,
+ "filename":"celery-2.0.3.tar.gz",
+ "has_sig":false,
+ "md5_digest":"824e934e56e5e4ac2d5b8bbe6eba8c50",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1082823,
+ "upload_time":"2010-08-27T12:53:02",
+ "upload_time_iso_8601":"2010-08-27T12:53:02.745489Z",
+ "url":"https://files.pythonhosted.org/packages/ae/4e/b3797d6b1ec7f60ac460492fe118115ff636970e0bb6d6ab53f3aa1384f8/celery-2.0.3.tar.gz"
+ }
+ ],
+ "2.1.0":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"dd7e2b38357a1c9641233d4627884109",
+ "sha256":"78d306d094e094e29ea3dbd766a8f6d0586686d8b70e8e1bcf099612ee4285dc"
+ },
+ "downloads":-1,
+ "filename":"celery-2.1.0.tar.gz",
+ "has_sig":false,
+ "md5_digest":"dd7e2b38357a1c9641233d4627884109",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1424761,
+ "upload_time":"2010-10-08T11:49:28",
+ "upload_time_iso_8601":"2010-10-08T11:49:28.632644Z",
+ "url":"https://files.pythonhosted.org/packages/93/b1/bf36d36ff626c686699f5a9162faec0914620f740d79604a7a1033c85d9d/celery-2.1.0.tar.gz"
+ }
+ ],
+ "2.1.1":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"5ecf0d03a5b4050ba6d207d28515ef7d",
+ "sha256":"3f161e65f7126aae20898d4b0b2c41f51d602d39a28612e0bc4e1ab2912f34ab"
+ },
+ "downloads":-1,
+ "filename":"celery-2.1.1.tar.gz",
+ "has_sig":false,
+ "md5_digest":"5ecf0d03a5b4050ba6d207d28515ef7d",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1427895,
+ "upload_time":"2010-10-14T14:22:54",
+ "upload_time_iso_8601":"2010-10-14T14:22:54.007507Z",
+ "url":"https://files.pythonhosted.org/packages/35/a8/19c376a01d086491c166d1644a357b8cd18c13db3a7ae3d08953d338ad86/celery-2.1.1.tar.gz"
+ }
+ ],
+ "2.1.2":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"54037484df43ca1104e3685da8fd2fa6",
+ "sha256":"f209ca3d19d953477bffb25e2e5a9911e20a38127bfc21beb68f26655b121ba0"
+ },
+ "downloads":-1,
+ "filename":"celery-2.1.2.tar.gz",
+ "has_sig":false,
+ "md5_digest":"54037484df43ca1104e3685da8fd2fa6",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1429767,
+ "upload_time":"2010-10-29T15:28:02",
+ "upload_time_iso_8601":"2010-10-29T15:28:02.562252Z",
+ "url":"https://files.pythonhosted.org/packages/be/34/606caa843ae459d3f3f05c8b03a9cc699038b427c4d67dfff1e9e5df0f14/celery-2.1.2.tar.gz"
+ }
+ ],
+ "2.1.3":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"029476100b9ba4763abc06da4fea2358",
+ "sha256":"80f6104ef7dbe46d5aadf044a755d7112eb31f083d73c90e1352e10faf5a1ccb"
+ },
+ "downloads":-1,
+ "filename":"celery-2.1.3.tar.gz",
+ "has_sig":false,
+ "md5_digest":"029476100b9ba4763abc06da4fea2358",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1430582,
+ "upload_time":"2010-11-09T16:02:03",
+ "upload_time_iso_8601":"2010-11-09T16:02:03.661686Z",
+ "url":"https://files.pythonhosted.org/packages/50/57/c9432fb792e72598ae7102e8b25ea2d522d680b120c8456b27b58245348f/celery-2.1.3.tar.gz"
+ }
+ ],
+ "2.1.4":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"1930be498c3278180d11e772435076ec",
+ "sha256":"156154cc009c06e2e787ddc7184b036168473a859067ad9a4b33de4ffa89278e"
+ },
+ "downloads":-1,
+ "filename":"celery-2.1.4.tar.gz",
+ "has_sig":false,
+ "md5_digest":"1930be498c3278180d11e772435076ec",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1442476,
+ "upload_time":"2010-12-03T16:11:49",
+ "upload_time_iso_8601":"2010-12-03T16:11:49.603043Z",
+ "url":"https://files.pythonhosted.org/packages/81/9d/3dcc36bded082122f22ba18c51317a61bf6b42ca965a40b66ff86d3dcf66/celery-2.1.4.tar.gz"
+ }
+ ],
+ "2.2.0":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"16e043ef274ccf2d658b6b0ee843f67b",
+ "sha256":"b4bd3bf091248eb21572ba829ea0fb96a35d8d6e50f9095937567d4f249b0453"
+ },
+ "downloads":-1,
+ "filename":"celery-2.2.0.tar.bz2",
+ "has_sig":false,
+ "md5_digest":"16e043ef274ccf2d658b6b0ee843f67b",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1405656,
+ "upload_time":"2011-02-01T11:05:07",
+ "upload_time_iso_8601":"2011-02-01T11:05:07.169728Z",
+ "url":"https://files.pythonhosted.org/packages/26/67/4507c8b17966429d84be4e33b70c9ce197748cf72157c97e2da8fbf7581c/celery-2.2.0.tar.bz2"
+ },
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"5affe85cab7fcb61c28218963c8d7eb3",
+ "sha256":"d3bfce8dcc753cfff4ce31397b27e13dfd10c321b4bdd4c4c386cd858bc42849"
+ },
+ "downloads":-1,
+ "filename":"celery-2.2.0.tar.gz",
+ "has_sig":false,
+ "md5_digest":"5affe85cab7fcb61c28218963c8d7eb3",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1486172,
+ "upload_time":"2011-02-01T11:02:41",
+ "upload_time_iso_8601":"2011-02-01T11:02:41.954271Z",
+ "url":"https://files.pythonhosted.org/packages/8d/81/0985bf4888493ebabb03cf14d1ace62e825771d1cdc93f3ba7df95e0ddd6/celery-2.2.0.tar.gz"
+ },
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"8ecb541e1d34143495f8899677cc8c7d",
+ "sha256":"d643b7748ae1423964be9ddac2e0a184205499c594529f94a78686659d3aba48"
+ },
+ "downloads":-1,
+ "filename":"celery-2.2.0.zip",
+ "has_sig":false,
+ "md5_digest":"8ecb541e1d34143495f8899677cc8c7d",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1693636,
+ "upload_time":"2011-02-01T11:05:10",
+ "upload_time_iso_8601":"2011-02-01T11:05:10.813490Z",
+ "url":"https://files.pythonhosted.org/packages/1d/4d/afa05d9d26b167a367b13e553d3c4c0ee3a84d1cd82e34f210fd39ed3705/celery-2.2.0.zip"
+ }
+ ],
+ "2.2.1":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"6055ffcd9ee9123257ad4d9bc0146c0a",
+ "sha256":"75e814bbad082fb9b0370e55d8bee7ecb8032d8104967d83e49157efd99ada3b"
+ },
+ "downloads":-1,
+ "filename":"celery-2.2.1.tar.bz2",
+ "has_sig":false,
+ "md5_digest":"6055ffcd9ee9123257ad4d9bc0146c0a",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1430407,
+ "upload_time":"2011-02-02T16:15:25",
+ "upload_time_iso_8601":"2011-02-02T16:15:25.474043Z",
+ "url":"https://files.pythonhosted.org/packages/50/7c/021e3e877f2c7bed8c1a5c8b76f3bdf6f29f74bb37f6a6d5bdd32c162880/celery-2.2.1.tar.bz2"
+ },
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"67a6a49ff4598b612decc0672b7758d5",
+ "sha256":"1c5e9dfff1b12d492b30d09220fa7e38eb13a74368cf53c440574d3f36ade912"
+ },
+ "downloads":-1,
+ "filename":"celery-2.2.1.tar.gz",
+ "has_sig":false,
+ "md5_digest":"67a6a49ff4598b612decc0672b7758d5",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1486647,
+ "upload_time":"2011-02-02T16:15:22",
+ "upload_time_iso_8601":"2011-02-02T16:15:22.510710Z",
+ "url":"https://files.pythonhosted.org/packages/f2/20/5393530f65effecbca5e344d97f3fd200c2ea87de1d5b9e15f4edced2a70/celery-2.2.1.tar.gz"
+ },
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"44c9e908cba22593a83414d8e1514977",
+ "sha256":"f6395749ae24c96d9e1caddb0e95257d3cc16b24d6e6ec3f038dc2f83f84bc63"
+ },
+ "downloads":-1,
+ "filename":"celery-2.2.1.zip",
+ "has_sig":false,
+ "md5_digest":"44c9e908cba22593a83414d8e1514977",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1694096,
+ "upload_time":"2011-02-02T16:15:19",
+ "upload_time_iso_8601":"2011-02-02T16:15:19.243781Z",
+ "url":"https://files.pythonhosted.org/packages/e2/d6/8eba060c3c29c6225c3bb944de78d80c930c97a302d4851879919d132e1f/celery-2.2.1.zip"
+ }
+ ],
+ "2.2.10":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"898bc87e54f278055b561316ba73e222",
+ "sha256":"dc6379c9bd0d799ed44e6a905d54b29fc0c7a514152e366bb3ef939e03291ab6"
+ },
+ "downloads":-1,
+ "filename":"celery-2.2.10.tar.gz",
+ "has_sig":false,
+ "md5_digest":"898bc87e54f278055b561316ba73e222",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1502041,
+ "upload_time":"2012-02-07T17:41:26",
+ "upload_time_iso_8601":"2012-02-07T17:41:26.485599Z",
+ "url":"https://files.pythonhosted.org/packages/b1/64/860fd50e45844c83442e7953effcddeff66b2851d90b2d784f7201c111b8/celery-2.2.10.tar.gz"
+ }
+ ],
+ "2.2.2":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"428716ef52f1e1f1fee4656c2705e708",
+ "sha256":"2e1188384b6974a4b83308cb7699c0e0b2a06fb36bc8ee00d1616473fcee3815"
+ },
+ "downloads":-1,
+ "filename":"celery-2.2.2.tar.bz2",
+ "has_sig":false,
+ "md5_digest":"428716ef52f1e1f1fee4656c2705e708",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1430918,
+ "upload_time":"2011-02-03T23:25:18",
+ "upload_time_iso_8601":"2011-02-03T23:25:18.939510Z",
+ "url":"https://files.pythonhosted.org/packages/b0/ea/cd451a99eacda0404deea3ddeda1c3ddb05d92208cf973661f1873d95821/celery-2.2.2.tar.bz2"
+ },
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"a3960153b8a7126a121bf2977e328fea",
+ "sha256":"6a8e9d1a884b51c43a87b3dfda9761f1b7e581af03e62858b259ead69660fdeb"
+ },
+ "downloads":-1,
+ "filename":"celery-2.2.2.tar.gz",
+ "has_sig":false,
+ "md5_digest":"a3960153b8a7126a121bf2977e328fea",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1487313,
+ "upload_time":"2011-02-03T23:25:15",
+ "upload_time_iso_8601":"2011-02-03T23:25:15.645846Z",
+ "url":"https://files.pythonhosted.org/packages/93/dd/56b2743eb789bbd360f93af019d6bb4bb5f95f00ebbd49615218c1e3d758/celery-2.2.2.tar.gz"
+ },
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"6c95343deb235a196973ef78408344fb",
+ "sha256":"8494c657625521de2cb21960e3154f8f7063321ae9e801fa531c89900b5d0a8d"
+ },
+ "downloads":-1,
+ "filename":"celery-2.2.2.zip",
+ "has_sig":false,
+ "md5_digest":"6c95343deb235a196973ef78408344fb",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1695007,
+ "upload_time":"2011-02-03T23:25:22",
+ "upload_time_iso_8601":"2011-02-03T23:25:22.645233Z",
+ "url":"https://files.pythonhosted.org/packages/94/a1/668e99f614b1e442063086f2b0ac822e65471d0bc20f5c6b239003ffc819/celery-2.2.2.zip"
+ }
+ ],
+ "2.2.3":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"3074e37245e2985c3bbc3aa6960fb750",
+ "sha256":"e26df3222d5ad05a8f2a2600fa1ce3c0d37bcbc4f46a29bde2568f312e0e68c1"
+ },
+ "downloads":-1,
+ "filename":"celery-2.2.3.tar.bz2",
+ "has_sig":false,
+ "md5_digest":"3074e37245e2985c3bbc3aa6960fb750",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1430852,
+ "upload_time":"2011-02-12T16:20:37",
+ "upload_time_iso_8601":"2011-02-12T16:20:37.538381Z",
+ "url":"https://files.pythonhosted.org/packages/2e/b8/58e2864a35ab0203e599f3725a63d39e3a564d56f816d4f4c82cbcee6833/celery-2.2.3.tar.bz2"
+ },
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"3878277c08157fd84d8632b99f9e7c03",
+ "sha256":"8633709fb08bded0b806d1c5ea3f7bb496e20df8f28673d3939985f31b49e0e0"
+ },
+ "downloads":-1,
+ "filename":"celery-2.2.3.tar.gz",
+ "has_sig":false,
+ "md5_digest":"3878277c08157fd84d8632b99f9e7c03",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1488878,
+ "upload_time":"2011-02-12T16:20:34",
+ "upload_time_iso_8601":"2011-02-12T16:20:34.567837Z",
+ "url":"https://files.pythonhosted.org/packages/44/82/f1f91578918064eb402d0f52f6cc8b5086cb0a1e5bff886f800ea0b4abbd/celery-2.2.3.tar.gz"
+ },
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"e5a990a84eceaeaf8add61a41b138eea",
+ "sha256":"10a3f89972e308d054e4ff5c714d1823a2508e603c119ec8893dbbe76fdc01e7"
+ },
+ "downloads":-1,
+ "filename":"celery-2.2.3.zip",
+ "has_sig":false,
+ "md5_digest":"e5a990a84eceaeaf8add61a41b138eea",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1695686,
+ "upload_time":"2011-02-12T16:20:40",
+ "upload_time_iso_8601":"2011-02-12T16:20:40.952658Z",
+ "url":"https://files.pythonhosted.org/packages/af/92/2a1988d889cf60e3008a51782b52900f5377e0b71ad7820d539555673168/celery-2.2.3.zip"
+ }
+ ],
+ "2.2.4":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"4bbdcf92735ac7366228bf578f9b1147",
+ "sha256":"72d4faec321e38321f0f891fe0be023de081eb9fb0cb0c4cdf4651914412f13b"
+ },
+ "downloads":-1,
+ "filename":"celery-2.2.4.tar.gz",
+ "has_sig":false,
+ "md5_digest":"4bbdcf92735ac7366228bf578f9b1147",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1492204,
+ "upload_time":"2011-02-19T23:45:31",
+ "upload_time_iso_8601":"2011-02-19T23:45:31.442510Z",
+ "url":"https://files.pythonhosted.org/packages/df/04/886803c5d26f9d50d1440f2557314b70f08b7a521d9ab06fac48e26ad719/celery-2.2.4.tar.gz"
+ }
+ ],
+ "2.2.5":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"d523c914a7c2761c70a4cc9058fdd6e8",
+ "sha256":"8f379b1b98cf9dd118896b6fe42721fa432016f3c34319fadd0772e6ef556a13"
+ },
+ "downloads":-1,
+ "filename":"celery-2.2.5.tar.gz",
+ "has_sig":false,
+ "md5_digest":"d523c914a7c2761c70a4cc9058fdd6e8",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1500347,
+ "upload_time":"2011-03-28T18:32:27",
+ "upload_time_iso_8601":"2011-03-28T18:32:27.548130Z",
+ "url":"https://files.pythonhosted.org/packages/74/01/53909028798a5a5b3563cc621ac0c6f4a88b1a6ee970702763863c7b0daf/celery-2.2.5.tar.gz"
+ }
+ ],
+ "2.2.6":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"0c8f5ec2535e2aaf692fd0227a5bb407",
+ "sha256":"244430e9c1b90fc70bb5eb45e3f20ea18201e59de5a35d27e2a74cfb0cd6d125"
+ },
+ "downloads":-1,
+ "filename":"celery-2.2.6.tar.gz",
+ "has_sig":false,
+ "md5_digest":"0c8f5ec2535e2aaf692fd0227a5bb407",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1501710,
+ "upload_time":"2011-04-15T15:25:15",
+ "upload_time_iso_8601":"2011-04-15T15:25:15.798614Z",
+ "url":"https://files.pythonhosted.org/packages/53/86/466b51b3fb2b5e319b7ba855927f327028e05d87b8229087cdfb0dd6a6bb/celery-2.2.6.tar.gz"
+ }
+ ],
+ "2.2.7":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"5826cf891eaa6175cc7aab67818094fe",
+ "sha256":"6a46d78ef81da35abab1c71627679ab7630d9666b3a774e2c4d8fb560a4b9da0"
+ },
+ "downloads":-1,
+ "filename":"celery-2.2.7.tar.gz",
+ "has_sig":false,
+ "md5_digest":"5826cf891eaa6175cc7aab67818094fe",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1502018,
+ "upload_time":"2011-06-13T16:18:41",
+ "upload_time_iso_8601":"2011-06-13T16:18:41.013844Z",
+ "url":"https://files.pythonhosted.org/packages/9c/eb/d63bf7c1d5548c7cb18a6fb415934a90ff845d32872a659738900da188cb/celery-2.2.7.tar.gz"
+ }
+ ],
+ "2.2.8":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"5aa94bea787b1fbb10c066c6b51dbafc",
+ "sha256":"cacd7be5b657513d6b2a49ef0c4418bfd057b1cc45c779bb9194671af4364e15"
+ },
+ "downloads":-1,
+ "filename":"celery-2.2.8.tar.gz",
+ "has_sig":false,
+ "md5_digest":"5aa94bea787b1fbb10c066c6b51dbafc",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1502049,
+ "upload_time":"2011-11-25T17:54:23",
+ "upload_time_iso_8601":"2011-11-25T17:54:23.954411Z",
+ "url":"https://files.pythonhosted.org/packages/91/e9/a33c624d1d4e4ad1a13bd97ca26b44366522771af66fd9c9b584af1eb673/celery-2.2.8.tar.gz"
+ }
+ ],
+ "2.2.9":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"21cd9d3c25fa3e855af480b96c345dc0",
+ "sha256":"216236e82ec0fbe7d097ef8c1182def355faf2fb07b039aa5e6ad846e1f11c14"
+ },
+ "downloads":-1,
+ "filename":"celery-2.2.9.tar.gz",
+ "has_sig":false,
+ "md5_digest":"21cd9d3c25fa3e855af480b96c345dc0",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1503856,
+ "upload_time":"2011-12-13T12:11:38",
+ "upload_time_iso_8601":"2011-12-13T12:11:38.995901Z",
+ "url":"https://files.pythonhosted.org/packages/23/a4/e49af8e757ece2987e47f04a56feeb135d7c65cbb45b13b6d147dbc57fe5/celery-2.2.9.tar.gz"
+ }
+ ],
+ "2.3.0":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"b2eec534b0bca07e5dd50c470ee99017",
+ "sha256":"313ed37f39176b2e734f6cae970ccd7b84b2aad7b186eb2a4adf9c12efbb3144"
+ },
+ "downloads":-1,
+ "filename":"celery-2.3.0.tar.gz",
+ "has_sig":false,
+ "md5_digest":"b2eec534b0bca07e5dd50c470ee99017",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":865346,
+ "upload_time":"2011-08-05T17:19:41",
+ "upload_time_iso_8601":"2011-08-05T17:19:41.978442Z",
+ "url":"https://files.pythonhosted.org/packages/69/da/ac56e297e0a3e442dd60fad008daa222e74b57df24b5450dcd73d99d9f4e/celery-2.3.0.tar.gz"
+ }
+ ],
+ "2.3.1":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"d41c6448f47148040e630a72faa8126e",
+ "sha256":"d832af6ca5ae0a94a9b5ccfa0cd853bee8b1f0b54226f4513bf3526f9e4df481"
+ },
+ "downloads":-1,
+ "filename":"celery-2.3.1.tar.gz",
+ "has_sig":false,
+ "md5_digest":"d41c6448f47148040e630a72faa8126e",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":866144,
+ "upload_time":"2011-08-07T23:25:00",
+ "upload_time_iso_8601":"2011-08-07T23:25:00.096051Z",
+ "url":"https://files.pythonhosted.org/packages/57/af/feac53f2b6fc5e971d60c1da8217efdc5f986cc147af119e588e3c9d7347/celery-2.3.1.tar.gz"
+ }
+ ],
+ "2.3.2":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"39c812d7bd14c54c4f24609dfe20e1bd",
+ "sha256":"ef75a7417138ca414ac8bc4539207bf21cdda8011e8790b15d65c1c2dbfd5e9a"
+ },
+ "downloads":-1,
+ "filename":"celery-2.3.2.tar.gz",
+ "has_sig":false,
+ "md5_digest":"39c812d7bd14c54c4f24609dfe20e1bd",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":870999,
+ "upload_time":"2011-09-07T17:57:06",
+ "upload_time_iso_8601":"2011-09-07T17:57:06.784281Z",
+ "url":"https://files.pythonhosted.org/packages/5d/c8/188313effbbfdf1e88f312c2014bb72be62286a124f1d1bda306a67ca758/celery-2.3.2.tar.gz"
+ }
+ ],
+ "2.3.3":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"fa6c661cf037b1b95ec81e67386bccb7",
+ "sha256":"f26240e98b73c84c4a2776abe1f2d3b0853dc36d19025f68f358be8e98a88e2e"
+ },
+ "downloads":-1,
+ "filename":"celery-2.3.3.tar.gz",
+ "has_sig":false,
+ "md5_digest":"fa6c661cf037b1b95ec81e67386bccb7",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":871312,
+ "upload_time":"2011-09-16T18:08:16",
+ "upload_time_iso_8601":"2011-09-16T18:08:16.153329Z",
+ "url":"https://files.pythonhosted.org/packages/38/10/a5d84d3bdee3e37f34a9f413999222c42531d3b4d1873dd32ff2e3269e21/celery-2.3.3.tar.gz"
+ }
+ ],
+ "2.3.4":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"f4b3693aac331d0c47b7f9c66aabdfe0",
+ "sha256":"59ee7c99c412b0df7e5396a5d617a0f7ac8c2060432e5983ff71b7a7dd8936dc"
+ },
+ "downloads":-1,
+ "filename":"celery-2.3.4.tar.gz",
+ "has_sig":false,
+ "md5_digest":"f4b3693aac331d0c47b7f9c66aabdfe0",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":871648,
+ "upload_time":"2011-11-25T17:47:51",
+ "upload_time_iso_8601":"2011-11-25T17:47:51.982305Z",
+ "url":"https://files.pythonhosted.org/packages/ca/00/5ddb92f4053eca182e3506d51aa202d2306b8b98884a6bcc685c19a99588/celery-2.3.4.tar.gz"
+ }
+ ],
+ "2.3.5":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"23893e021d172ebf330f850fe9366b99",
+ "sha256":"696501cda0fb0384624290028c3cd11fe2008cd47cfa8e09493c2d738fc44007"
+ },
+ "downloads":-1,
+ "filename":"celery-2.3.5.tar.gz",
+ "has_sig":false,
+ "md5_digest":"23893e021d172ebf330f850fe9366b99",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":871796,
+ "upload_time":"2011-12-28T14:23:04",
+ "upload_time_iso_8601":"2011-12-28T14:23:04.895711Z",
+ "url":"https://files.pythonhosted.org/packages/01/0a/ea2859892c53b8829ceee0bff028645e237afcf4680d8278f5f5ff971ec4/celery-2.3.5.tar.gz"
+ }
+ ],
+ "2.4.0":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"ebf718d2f50af2b81eba8e9c939c1c50",
+ "sha256":"81fd64381c1834a90b9d4661fa5bdd1313900acc467e7f9cee887d8780de8fb9"
+ },
+ "downloads":-1,
+ "filename":"celery-2.4.0.tar.gz",
+ "has_sig":false,
+ "md5_digest":"ebf718d2f50af2b81eba8e9c939c1c50",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":887849,
+ "upload_time":"2011-11-04T16:27:40",
+ "upload_time_iso_8601":"2011-11-04T16:27:40.093799Z",
+ "url":"https://files.pythonhosted.org/packages/e1/af/4869eb4780d3013e069b3083afba2dec1d760ea17fee8095fd2f6380fdeb/celery-2.4.0.tar.gz"
+ }
+ ],
+ "2.4.1":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"482b2ed34e9055f4138d92e6dc272475",
+ "sha256":"c77652ca179d14473975822dbfb1b5dab950c88c171ef6bc2257ddb9066e6790"
+ },
+ "downloads":-1,
+ "filename":"celery-2.4.1.tar.gz",
+ "has_sig":false,
+ "md5_digest":"482b2ed34e9055f4138d92e6dc272475",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":887466,
+ "upload_time":"2011-11-07T22:47:12",
+ "upload_time_iso_8601":"2011-11-07T22:47:12.797071Z",
+ "url":"https://files.pythonhosted.org/packages/70/d1/d3ce2909255ce04994359b9961d4158d8ec3e726d121549e1dab5b8be76a/celery-2.4.1.tar.gz"
+ }
+ ],
+ "2.4.2":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"79539ddc91d9f94c08de2a45107eebbc",
+ "sha256":"be56ff5a92892e352291810da31d5d413b656dc435d0268c8fe9cdf9f9b06b16"
+ },
+ "downloads":-1,
+ "filename":"celery-2.4.2.tar.gz",
+ "has_sig":false,
+ "md5_digest":"79539ddc91d9f94c08de2a45107eebbc",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":888524,
+ "upload_time":"2011-11-14T12:32:59",
+ "upload_time_iso_8601":"2011-11-14T12:32:59.990052Z",
+ "url":"https://files.pythonhosted.org/packages/8a/72/110885bf8fbbb6d0e75998ca6604d870811bda3c7af49dde9d25f86ddba9/celery-2.4.2.tar.gz"
+ }
+ ],
+ "2.4.3":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"4fa3ca632ce2e9fad9fcd99fa23d221e",
+ "sha256":"a832c1220b1bb4206dbb57515c1bbc164aeddae797977d7f99cc1b94dff40de0"
+ },
+ "downloads":-1,
+ "filename":"celery-2.4.3.tar.gz",
+ "has_sig":false,
+ "md5_digest":"4fa3ca632ce2e9fad9fcd99fa23d221e",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":888539,
+ "upload_time":"2011-11-22T18:21:12",
+ "upload_time_iso_8601":"2011-11-22T18:21:12.916880Z",
+ "url":"https://files.pythonhosted.org/packages/ad/bc/0d6abd73655bf4844e018628b5868a124358af4e8a2896a965e58c188506/celery-2.4.3.tar.gz"
+ }
+ ],
+ "2.4.4":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"e168bc9856b263edcb0801a04eb9ee9f",
+ "sha256":"7d6e5b12717aa688e10007862bd62a65f540b8c6b5e23a67f99341e1abfc0cc4"
+ },
+ "downloads":-1,
+ "filename":"celery-2.4.4.tar.gz",
+ "has_sig":false,
+ "md5_digest":"e168bc9856b263edcb0801a04eb9ee9f",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":889111,
+ "upload_time":"2011-11-25T18:24:08",
+ "upload_time_iso_8601":"2011-11-25T18:24:08.827869Z",
+ "url":"https://files.pythonhosted.org/packages/b8/5d/9394e874de3151defad5eb77cb2827798ac777e90cb2b9dd2ea0c938e92d/celery-2.4.4.tar.gz"
+ }
+ ],
+ "2.4.5":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"a8648b3fa9e0cdd6b6a4be71d7f496c8",
+ "sha256":"9203ab223f8c36b7c60fcf7ab3012a0c2a8be13517d5e3007d2866d15a06be67"
+ },
+ "downloads":-1,
+ "filename":"celery-2.4.5.tar.gz",
+ "has_sig":true,
+ "md5_digest":"a8648b3fa9e0cdd6b6a4be71d7f496c8",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":892282,
+ "upload_time":"2011-12-02T18:39:18",
+ "upload_time_iso_8601":"2011-12-02T18:39:18.843132Z",
+ "url":"https://files.pythonhosted.org/packages/d7/a5/21ddeeb1afc5ab23b470133716bc030fa391e2002944bbf6f5ce31748ef6/celery-2.4.5.tar.gz"
+ }
+ ],
+ "2.4.6":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"a480dd8741b0d5ed694b6a36a25a47ce",
+ "sha256":"59d2c8067bb10d6558e524131e38d5c7684fba0211dbd58229bc73f16334f0b4"
+ },
+ "downloads":-1,
+ "filename":"celery-2.4.6.tar.gz",
+ "has_sig":false,
+ "md5_digest":"a480dd8741b0d5ed694b6a36a25a47ce",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":892396,
+ "upload_time":"2011-12-28T14:26:21",
+ "upload_time_iso_8601":"2011-12-28T14:26:21.292212Z",
+ "url":"https://files.pythonhosted.org/packages/d6/ab/3741995520ca6b13bc1ecb3844f6eac4402ca374a589383c714f9cd60503/celery-2.4.6.tar.gz"
+ }
+ ],
+ "2.4.7":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"4c9072ec0ec0480b63e1e4ad4765d5ce",
+ "sha256":"bc30eca26a0adc23b00fc7362be36adcd6aaeed31059e393ae20745b9babbfeb"
+ },
+ "downloads":-1,
+ "filename":"celery-2.4.7.tar.gz",
+ "has_sig":false,
+ "md5_digest":"4c9072ec0ec0480b63e1e4ad4765d5ce",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":892513,
+ "upload_time":"2012-07-11T00:42:19",
+ "upload_time_iso_8601":"2012-07-11T00:42:19.224120Z",
+ "url":"https://files.pythonhosted.org/packages/9c/7f/e4adc8a54010c7668cb99ebdd45da74bf6a87da9d92396788c9f993d5e5b/celery-2.4.7.tar.gz"
+ }
+ ],
+ "2.5.0":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"0a207f123bed26c8e9634cd0c179abc0",
+ "sha256":"d4f2ea1dd01cd3b82f85b8e402b3efd29dd3d12a96b8e9f66c094fe606ea0cb8"
+ },
+ "downloads":-1,
+ "filename":"celery-2.5.0.tar.gz",
+ "has_sig":false,
+ "md5_digest":"0a207f123bed26c8e9634cd0c179abc0",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":941813,
+ "upload_time":"2012-02-24T17:19:56",
+ "upload_time_iso_8601":"2012-02-24T17:19:56.972928Z",
+ "url":"https://files.pythonhosted.org/packages/9f/97/4f73bc4d1ec2533485addb24650a96e9c184fb47cc861ca44687df31177e/celery-2.5.0.tar.gz"
+ }
+ ],
+ "2.5.1":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"c0912f29b69929219b353c748e0bf936",
+ "sha256":"aa9950aec83b38eae74382a690e8d9bfd58ec510823b61a142d563489aa753b3"
+ },
+ "downloads":-1,
+ "filename":"celery-2.5.1.tar.gz",
+ "has_sig":false,
+ "md5_digest":"c0912f29b69929219b353c748e0bf936",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":942335,
+ "upload_time":"2012-03-01T13:51:14",
+ "upload_time_iso_8601":"2012-03-01T13:51:14.094533Z",
+ "url":"https://files.pythonhosted.org/packages/2b/2b/8328e9bc884e66f0b19c80528c64e56782a7bed4873e0aa4bdb4585fc4a4/celery-2.5.1.tar.gz"
+ }
+ ],
+ "2.5.2":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"2c49deb7bdf470d9f77916d688e68687",
+ "sha256":"702af4ecd05b2cde1a6a964dedf1e7e370f90f3b1c37c07cae2382d6c983c12c"
+ },
+ "downloads":-1,
+ "filename":"celery-2.5.2.tar.gz",
+ "has_sig":false,
+ "md5_digest":"2c49deb7bdf470d9f77916d688e68687",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":945885,
+ "upload_time":"2012-04-13T17:36:51",
+ "upload_time_iso_8601":"2012-04-13T17:36:51.726034Z",
+ "url":"https://files.pythonhosted.org/packages/5b/d3/6af7f863f79218b20995172a9a8af8e1ee28dc73ab1df0b858a29daacb7d/celery-2.5.2.tar.gz"
+ }
+ ],
+ "2.5.3":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"a3361c800fb8455e1e50024aaa940f07",
+ "sha256":"30bef144a62fb978dd81bef848f30f8df30b5e9a22171dc582b8d3332acae726"
+ },
+ "downloads":-1,
+ "filename":"celery-2.5.3.tar.gz",
+ "has_sig":false,
+ "md5_digest":"a3361c800fb8455e1e50024aaa940f07",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":946218,
+ "upload_time":"2012-04-16T19:51:37",
+ "upload_time_iso_8601":"2012-04-16T19:51:37.526451Z",
+ "url":"https://files.pythonhosted.org/packages/43/2c/d515f5b12fc1474697730094a5f9b09bfa870544f08c39b012a8f831d45d/celery-2.5.3.tar.gz"
+ }
+ ],
+ "2.5.5":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"9fa40c1300d18e176db63f833a378647",
+ "sha256":"0aa6a5660a21d5b33ae6192035c1711302199329d714f8a48ddf8c88d93b9c83"
+ },
+ "downloads":-1,
+ "filename":"celery-2.5.5.tar.gz",
+ "has_sig":false,
+ "md5_digest":"9fa40c1300d18e176db63f833a378647",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":945555,
+ "upload_time":"2012-06-07T12:18:26",
+ "upload_time_iso_8601":"2012-06-07T12:18:26.169237Z",
+ "url":"https://files.pythonhosted.org/packages/8e/69/318d91bc367134a85db5749cd50ecee5e3c87455df040ef4c51251c6bbbb/celery-2.5.5.tar.gz"
+ }
+ ],
+ "3.0.0":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"4db351ac5943424c020386322816b0c2",
+ "sha256":"04c625c37aa456ccf92038be638a9f4ff152527de73c4e3f46e80268b83a0810"
+ },
+ "downloads":-1,
+ "filename":"celery-3.0.0.tar.gz",
+ "has_sig":false,
+ "md5_digest":"4db351ac5943424c020386322816b0c2",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":955774,
+ "upload_time":"2012-07-07T13:59:33",
+ "upload_time_iso_8601":"2012-07-07T13:59:33.983349Z",
+ "url":"https://files.pythonhosted.org/packages/88/3e/d2a0d310fd4a0ab7dca0fbde1b5d531f6409536559bba0cdbb98997bc58d/celery-3.0.0.tar.gz"
+ }
+ ],
+ "3.0.1":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"64cd59537ddda0b32ef3e54935650771",
+ "sha256":"1fcef1cf270455ddf76190130ad4b11b3edf1b2a2d39c9bec42beed9a9b62683"
+ },
+ "downloads":-1,
+ "filename":"celery-3.0.1.tar.gz",
+ "has_sig":false,
+ "md5_digest":"64cd59537ddda0b32ef3e54935650771",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":957999,
+ "upload_time":"2012-07-10T19:10:26",
+ "upload_time_iso_8601":"2012-07-10T19:10:26.946182Z",
+ "url":"https://files.pythonhosted.org/packages/b4/e2/1790137c63291d180a127cd24f0e13ca200c391ad2f654fb5279b8e1faa9/celery-3.0.1.tar.gz"
+ }
+ ],
+ "3.0.10":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"41247bf42627f5ca26bd9de597f4922a",
+ "sha256":"5df5e8e79956cbd3e1a8d7a982f196be0d487212a7b25765b58f45a0ef52f934"
+ },
+ "downloads":-1,
+ "filename":"celery-3.0.10.tar.gz",
+ "has_sig":false,
+ "md5_digest":"41247bf42627f5ca26bd9de597f4922a",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1217114,
+ "upload_time":"2012-09-20T16:35:50",
+ "upload_time_iso_8601":"2012-09-20T16:35:50.817111Z",
+ "url":"https://files.pythonhosted.org/packages/bc/58/9eb5433c3c565abf50ab48c77cdb8d4fb97a3ad963c7125980036f5d655c/celery-3.0.10.tar.gz"
+ }
+ ],
+ "3.0.11":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"1d54cbb3a784424ddc9bfdd4d7be617b",
+ "sha256":"cf21361896a095bc602fe531b56fe6b58961233053fac43952abdeaa569e4951"
+ },
+ "downloads":-1,
+ "filename":"celery-3.0.11.tar.gz",
+ "has_sig":false,
+ "md5_digest":"1d54cbb3a784424ddc9bfdd4d7be617b",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1218453,
+ "upload_time":"2012-09-26T17:04:01",
+ "upload_time_iso_8601":"2012-09-26T17:04:01.456893Z",
+ "url":"https://files.pythonhosted.org/packages/99/66/d45be99ad0b8fff1327d41fbd8be8a760085de3b2abc5a0df8818adcc56c/celery-3.0.11.tar.gz"
+ }
+ ],
+ "3.0.12":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"a428b84562f61955d752bdff5e612f80",
+ "sha256":"716a465327ded5048893d518eafdade5eb09eb9d941e6efdbdaaac73b0251d3d"
+ },
+ "downloads":-1,
+ "filename":"celery-3.0.12.tar.gz",
+ "has_sig":false,
+ "md5_digest":"a428b84562f61955d752bdff5e612f80",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1218262,
+ "upload_time":"2012-11-06T14:36:47",
+ "upload_time_iso_8601":"2012-11-06T14:36:47.241192Z",
+ "url":"https://files.pythonhosted.org/packages/25/e1/c0002aa3d1a267c31aac647c3cd3c7df8b07959238f17812971f4d630b6e/celery-3.0.12.tar.gz"
+ }
+ ],
+ "3.0.13":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"5ca2ed5f71203240c4e7894f4aa7a77d",
+ "sha256":"1a8d045c94bfda832db2afbc786e8c99ac0e094d6019a5d89c8adfe04f396d6a"
+ },
+ "downloads":-1,
+ "filename":"celery-3.0.13.tar.gz",
+ "has_sig":false,
+ "md5_digest":"5ca2ed5f71203240c4e7894f4aa7a77d",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1223019,
+ "upload_time":"2013-01-07T16:00:37",
+ "upload_time_iso_8601":"2013-01-07T16:00:37.111172Z",
+ "url":"https://files.pythonhosted.org/packages/e1/d4/41233c02bef4440ae598485fc08bbaacf709b65001dc3fb3d142bbd45483/celery-3.0.13.tar.gz"
+ }
+ ],
+ "3.0.14":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"7fb39e064233becce9b13b7f9dfaca08",
+ "sha256":"57006a6e477282a2e55ace498729bf13218ac2c7ad5d9d920ad86b2469458df2"
+ },
+ "downloads":-1,
+ "filename":"celery-3.0.14.tar.gz",
+ "has_sig":false,
+ "md5_digest":"7fb39e064233becce9b13b7f9dfaca08",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1229097,
+ "upload_time":"2013-02-08T17:51:03",
+ "upload_time_iso_8601":"2013-02-08T17:51:03.401577Z",
+ "url":"https://files.pythonhosted.org/packages/ec/48/794f01cd79907a36de4d9bf512b80dd91ab33fb4f70134de5df56414aa94/celery-3.0.14.tar.gz"
+ }
+ ],
+ "3.0.15":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"5ac83d2cdcacf230897d9bffcf0ddbd9",
+ "sha256":"c20637d2ad68ddc407f4fba89e3afccbe7a9c55a3b79059579ba9fcf5de5d976"
+ },
+ "downloads":-1,
+ "filename":"celery-3.0.15.tar.gz",
+ "has_sig":false,
+ "md5_digest":"5ac83d2cdcacf230897d9bffcf0ddbd9",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1229180,
+ "upload_time":"2013-02-11T16:32:31",
+ "upload_time_iso_8601":"2013-02-11T16:32:31.930096Z",
+ "url":"https://files.pythonhosted.org/packages/47/d0/1db53a66fbbcd77e8594c7a45576a5d4325b01e3640ecfbdfedc79883ecf/celery-3.0.15.tar.gz"
+ }
+ ],
+ "3.0.16":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"ebc0636683df28b7d2dc8b06a948eecb",
+ "sha256":"31dc01e2e9c52825419d760422de7a6ce6fc789960fa087e8227ff4a528a2120"
+ },
+ "downloads":-1,
+ "filename":"celery-3.0.16.tar.gz",
+ "has_sig":false,
+ "md5_digest":"ebc0636683df28b7d2dc8b06a948eecb",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1233799,
+ "upload_time":"2013-03-08T15:40:41",
+ "upload_time_iso_8601":"2013-03-08T15:40:41.783771Z",
+ "url":"https://files.pythonhosted.org/packages/e7/49/bc7f9312d2269f8717ec7706e9b9283bbf68baaef8c5a0e8b1a0add9e31b/celery-3.0.16.tar.gz"
+ }
+ ],
+ "3.0.17":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"50491556f2b521d249da6f30112dfcb9",
+ "sha256":"554d1e0c7cd8346aa372bb7f2b971441eee8e192a6a3855c89bad4d33b7bd947"
+ },
+ "downloads":-1,
+ "filename":"celery-3.0.17.tar.gz",
+ "has_sig":false,
+ "md5_digest":"50491556f2b521d249da6f30112dfcb9",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1235117,
+ "upload_time":"2013-03-22T16:06:25",
+ "upload_time_iso_8601":"2013-03-22T16:06:25.651019Z",
+ "url":"https://files.pythonhosted.org/packages/d8/83/9e7f8df01cbcf3727ba80dcb8ef85f4dad7b10ab504447ca349bc732f0d5/celery-3.0.17.tar.gz"
+ }
+ ],
+ "3.0.18":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"ca1a7027e229c9cc99a16d9852cebc3e",
+ "sha256":"00350c6041efb19136857693d2b90a85afbe9dfce4f9a473ce945405fa3dd8a9"
+ },
+ "downloads":-1,
+ "filename":"celery-3.0.18.tar.gz",
+ "has_sig":false,
+ "md5_digest":"ca1a7027e229c9cc99a16d9852cebc3e",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1240084,
+ "upload_time":"2013-04-12T16:20:10",
+ "upload_time_iso_8601":"2013-04-12T16:20:10.053224Z",
+ "url":"https://files.pythonhosted.org/packages/03/a9/b803a9593a2ca103e273e51e53e5527a6647a39cd0d71cec7ede42d24695/celery-3.0.18.tar.gz"
+ }
+ ],
+ "3.0.19":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"267c4fe4fdff3f7b722ca24327f49d64",
+ "sha256":"70ce2ff1143d964378b3e50817366256a036e78422e85cd89724d5e6ef022e55"
+ },
+ "downloads":-1,
+ "filename":"celery-3.0.19.tar.gz",
+ "has_sig":false,
+ "md5_digest":"267c4fe4fdff3f7b722ca24327f49d64",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1242004,
+ "upload_time":"2013-04-17T15:19:30",
+ "upload_time_iso_8601":"2013-04-17T15:19:30.135279Z",
+ "url":"https://files.pythonhosted.org/packages/aa/f7/c9f193f422364f97e51278771b6922213bce1962eacdd242e3a28283a4e5/celery-3.0.19.tar.gz"
+ }
+ ],
+ "3.0.2":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"da94277538270855921809f2dee67614",
+ "sha256":"1dcb412d4c94dd46b25c392c5aafd5852ff9ada69ebc81a4570b85743ac605d6"
+ },
+ "downloads":-1,
+ "filename":"celery-3.0.2.tar.gz",
+ "has_sig":false,
+ "md5_digest":"da94277538270855921809f2dee67614",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":961658,
+ "upload_time":"2012-07-20T17:36:59",
+ "upload_time_iso_8601":"2012-07-20T17:36:59.166671Z",
+ "url":"https://files.pythonhosted.org/packages/22/f0/e3e09fbd5ffe0b08c6918fdbda004e95c28ce2914310588148e39ef3813c/celery-3.0.2.tar.gz"
+ }
+ ],
+ "3.0.20":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"13c62d862d3cc108c4b661d7ea58f0c7",
+ "sha256":"a401afb35fb909710a1483f2a2657c9f72010e307985b42125c04547fb935727"
+ },
+ "downloads":-1,
+ "filename":"celery-3.0.20.tar.gz",
+ "has_sig":false,
+ "md5_digest":"13c62d862d3cc108c4b661d7ea58f0c7",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1094641,
+ "upload_time":"2013-06-28T14:41:36",
+ "upload_time_iso_8601":"2013-06-28T14:41:36.185262Z",
+ "url":"https://files.pythonhosted.org/packages/f8/24/c89cbc65ce1909ad9888a5fb8c8ac8229a83fda46a20e587bf713b0a4c1b/celery-3.0.20.tar.gz"
+ }
+ ],
+ "3.0.21":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"73885b62957af0b844f41d4acca9778c",
+ "sha256":"c1a76a94ba0d766630678df4912e211dc916f73143a189f8a6e37148ad2ffa53"
+ },
+ "downloads":-1,
+ "filename":"celery-3.0.21.tar.gz",
+ "has_sig":false,
+ "md5_digest":"73885b62957af0b844f41d4acca9778c",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1094747,
+ "upload_time":"2013-07-05T15:18:15",
+ "upload_time_iso_8601":"2013-07-05T15:18:15.843842Z",
+ "url":"https://files.pythonhosted.org/packages/30/1b/a95d938e7b3f2c983cc5fa1ec0b50750d471b9421d7c992810a4ed78752e/celery-3.0.21.tar.gz"
+ }
+ ],
+ "3.0.22":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"faa7881c5d051257829b5a292c922da3",
+ "sha256":"2ba77bc0dc0c9079e6aa1b3649174c3d002bc0896e9a155f435ef5d761406e89"
+ },
+ "downloads":-1,
+ "filename":"celery-3.0.22.tar.gz",
+ "has_sig":false,
+ "md5_digest":"faa7881c5d051257829b5a292c922da3",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1095861,
+ "upload_time":"2013-08-16T16:01:52",
+ "upload_time_iso_8601":"2013-08-16T16:01:52.547191Z",
+ "url":"https://files.pythonhosted.org/packages/42/80/54076a5b6ff52db5106dcacf512c5714aac389d9d3d1e403cc0929bca75f/celery-3.0.22.tar.gz"
+ }
+ ],
+ "3.0.23":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"095a80df47adf153f2826429282ae176",
+ "sha256":"d266c4428bd31de7fe5ba364a35717e4a592b574158363302ad4f13601835ace"
+ },
+ "downloads":-1,
+ "filename":"celery-3.0.23.tar.gz",
+ "has_sig":false,
+ "md5_digest":"095a80df47adf153f2826429282ae176",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1096420,
+ "upload_time":"2013-09-02T12:00:29",
+ "upload_time_iso_8601":"2013-09-02T12:00:29.186159Z",
+ "url":"https://files.pythonhosted.org/packages/30/26/ce4cdbae333ff95c1bd3d433a5f000882508cb0f0e5cfb24bf6da74e7b70/celery-3.0.23.tar.gz"
+ }
+ ],
+ "3.0.24":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"e864856a849468f277031ac2c5fd65b6",
+ "sha256":"68620192ec0b2212e64c307b5588c6c02f6a56e21160f3f3323653f7e44aafdf"
+ },
+ "downloads":-1,
+ "filename":"celery-3.0.24.tar.gz",
+ "has_sig":false,
+ "md5_digest":"e864856a849468f277031ac2c5fd65b6",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1097427,
+ "upload_time":"2013-10-11T16:37:44",
+ "upload_time_iso_8601":"2013-10-11T16:37:44.536773Z",
+ "url":"https://files.pythonhosted.org/packages/7f/60/40867734f08257bd0fdf25daa08a860e4b38127cfeae7768dc33809478aa/celery-3.0.24.tar.gz"
+ }
+ ],
+ "3.0.25":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"f869b9ddca813f33e844e77fc9708a19",
+ "sha256":"3e8c74cc76819082204754a699cb3372176e7c95a19c8b2e1057b463392fb734"
+ },
+ "downloads":-1,
+ "filename":"celery-3.0.25.tar.gz",
+ "has_sig":true,
+ "md5_digest":"f869b9ddca813f33e844e77fc9708a19",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1099104,
+ "upload_time":"2014-07-10T20:58:29",
+ "upload_time_iso_8601":"2014-07-10T20:58:29.073468Z",
+ "url":"https://files.pythonhosted.org/packages/4e/9d/560053fdb8e79cb6c6afcf9ef0fd9ee5a5038c2ea0d4b88fa5e530ba72e5/celery-3.0.25.tar.gz"
+ }
+ ],
+ "3.0.3":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"65058a8c11c50480d6468154b2718d52",
+ "sha256":"2bf1660eda36efd4343c82934f951609ccce2c215f0abc06c151d981b4fc57d1"
+ },
+ "downloads":-1,
+ "filename":"celery-3.0.3.tar.gz",
+ "has_sig":false,
+ "md5_digest":"65058a8c11c50480d6468154b2718d52",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":961793,
+ "upload_time":"2012-07-20T22:21:04",
+ "upload_time_iso_8601":"2012-07-20T22:21:04.756199Z",
+ "url":"https://files.pythonhosted.org/packages/94/b4/acc895c29f371083388d8b3037ac10a9d462b8e1368e2e43fc2b61c9dc3f/celery-3.0.3.tar.gz"
+ }
+ ],
+ "3.0.4":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"f4844c044716b1d3adbae6cb545ff24d",
+ "sha256":"9e0bca9bed35c05d66c3b5357b643a6f1e1ccaec5d59c89ab4ec2c3b830be274"
+ },
+ "downloads":-1,
+ "filename":"celery-3.0.4.tar.gz",
+ "has_sig":false,
+ "md5_digest":"f4844c044716b1d3adbae6cb545ff24d",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1058430,
+ "upload_time":"2012-07-26T21:06:38",
+ "upload_time_iso_8601":"2012-07-26T21:06:38.011882Z",
+ "url":"https://files.pythonhosted.org/packages/3c/4a/ae7988ee5afc3864261fdaef132348dfefe5c3168b2505711f774b253292/celery-3.0.4.tar.gz"
+ }
+ ],
+ "3.0.5":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"bf2ea38d572c7bd976810b6b4b6c1e3d",
+ "sha256":"d56704aa8db8be54dde1fd41cf3946c210ac712f358816a95e418a987030a18e"
+ },
+ "downloads":-1,
+ "filename":"celery-3.0.5.tar.gz",
+ "has_sig":false,
+ "md5_digest":"bf2ea38d572c7bd976810b6b4b6c1e3d",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1058986,
+ "upload_time":"2012-08-01T17:33:00",
+ "upload_time_iso_8601":"2012-08-01T17:33:00.063440Z",
+ "url":"https://files.pythonhosted.org/packages/6f/26/4df4631d72323152ca04f441a792fe6b875b168dae00ce29eb28e95f7227/celery-3.0.5.tar.gz"
+ }
+ ],
+ "3.0.6":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"71429442f8250be5a809faf140556340",
+ "sha256":"65cbfedff0443a9e9a098be7b0fd496c174b13d24612092f7ac3eef18df3c3b9"
+ },
+ "downloads":-1,
+ "filename":"celery-3.0.6.tar.gz",
+ "has_sig":false,
+ "md5_digest":"71429442f8250be5a809faf140556340",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1208874,
+ "upload_time":"2012-08-17T22:20:07",
+ "upload_time_iso_8601":"2012-08-17T22:20:07.228420Z",
+ "url":"https://files.pythonhosted.org/packages/f8/b7/4db2e65f366ec254edb4e5c21f38710598eb35c1174a065ca19f927783ff/celery-3.0.6.tar.gz"
+ }
+ ],
+ "3.0.7":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"a3b2240ad928c13bd8e075f0f5ec0d4b",
+ "sha256":"1a05c1f9d8de3c11f1f9e7a3f62277186f5c7f250ce168af17ca79325d73ce4a"
+ },
+ "downloads":-1,
+ "filename":"celery-3.0.7.tar.gz",
+ "has_sig":false,
+ "md5_digest":"a3b2240ad928c13bd8e075f0f5ec0d4b",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1210218,
+ "upload_time":"2012-08-24T16:55:21",
+ "upload_time_iso_8601":"2012-08-24T16:55:21.594830Z",
+ "url":"https://files.pythonhosted.org/packages/e1/d2/01f5437437f570359ea33183073b9364f8f70d5b767fa21358b8056909f4/celery-3.0.7.tar.gz"
+ }
+ ],
+ "3.0.8":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"248c47aa21440b9c716512ead00272f0",
+ "sha256":"a992e4f28391920bf0c6e1a17ca79b6a3d15b334710913c93103b66b210f1fe3"
+ },
+ "downloads":-1,
+ "filename":"celery-3.0.8.tar.gz",
+ "has_sig":false,
+ "md5_digest":"248c47aa21440b9c716512ead00272f0",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1211460,
+ "upload_time":"2012-08-29T16:05:38",
+ "upload_time_iso_8601":"2012-08-29T16:05:38.607795Z",
+ "url":"https://files.pythonhosted.org/packages/a9/d1/e4dd4d9755bd338538ad6608be74c95c096bfff6c1efe91b134dc4424dc7/celery-3.0.8.tar.gz"
+ }
+ ],
+ "3.0.9":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"894d5dcc281be4a6d0dce16c9cc02e57",
+ "sha256":"5ca0156feb7de5fec47e0aa8e275039cb78e1f32842b59635c786a877e45b1de"
+ },
+ "downloads":-1,
+ "filename":"celery-3.0.9.tar.gz",
+ "has_sig":false,
+ "md5_digest":"894d5dcc281be4a6d0dce16c9cc02e57",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1213486,
+ "upload_time":"2012-08-31T16:58:17",
+ "upload_time_iso_8601":"2012-08-31T16:58:17.854866Z",
+ "url":"https://files.pythonhosted.org/packages/5d/18/11116de4b0d30a2e596df870fea4e0bd0b2e5c90d0e895c1d5c17edad6b1/celery-3.0.9.tar.gz"
+ }
+ ],
+ "3.1.0":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"1283d31277361748855a43f6869b8c47",
+ "sha256":"b7abee4860cf1ee056a040950578c9c26278f46207df299e80f4ac74171eaf0f"
+ },
+ "downloads":-1,
+ "filename":"celery-3.1.0.tar.gz",
+ "has_sig":true,
+ "md5_digest":"1283d31277361748855a43f6869b8c47",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1267586,
+ "upload_time":"2013-11-09T23:04:06",
+ "upload_time_iso_8601":"2013-11-09T23:04:06.666458Z",
+ "url":"https://files.pythonhosted.org/packages/4c/41/73889bb38bce56ace75772fe253eeb2b5f27317acbf946573b83d55aa602/celery-3.1.0.tar.gz"
+ }
+ ],
+ "3.1.1":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"22396dd44cb3147a6d79c25f8960abab",
+ "sha256":"a9b816a7451d42b129e915d373132ae578f882acd8795d26343a84e887aabc68"
+ },
+ "downloads":-1,
+ "filename":"celery-3.1.1.tar.gz",
+ "has_sig":true,
+ "md5_digest":"22396dd44cb3147a6d79c25f8960abab",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1269075,
+ "upload_time":"2013-11-11T19:21:46",
+ "upload_time_iso_8601":"2013-11-11T19:21:46.638890Z",
+ "url":"https://files.pythonhosted.org/packages/c9/7d/df5ceb367c8c8d8372a28aa384166f8f998f62f8c4b1028794df38cc7163/celery-3.1.1.tar.gz"
+ }
+ ],
+ "3.1.10":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"c56a63e89de1c507ff20d676120c7b13",
+ "sha256":"1cfdcc12b8208df414386e0c9ae0cef7aff7ee11babf63c3319e0e991972059e"
+ },
+ "downloads":-1,
+ "filename":"celery-3.1.10-py27-none-any.whl",
+ "has_sig":true,
+ "md5_digest":"c56a63e89de1c507ff20d676120c7b13",
+ "packagetype":"bdist_wheel",
+ "python_version":"2.7",
+ "requires_python":null,
+ "size":512857,
+ "upload_time":"2014-03-22T21:47:15",
+ "upload_time_iso_8601":"2014-03-22T21:47:15.696509Z",
+ "url":"https://files.pythonhosted.org/packages/69/fb/5595ddf29fd1feaf5abd062ad997b547ee3096b5ee62ec83008a1ac34973/celery-3.1.10-py27-none-any.whl"
+ },
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"b172ac3047be77cadda516214a720cb6",
+ "sha256":"0c292e17d439db20e10e07dd78ef51ec1d748af78cf247b69ee02bbce4923d36"
+ },
+ "downloads":-1,
+ "filename":"celery-3.1.10.tar.gz",
+ "has_sig":true,
+ "md5_digest":"b172ac3047be77cadda516214a720cb6",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1287618,
+ "upload_time":"2014-03-22T21:45:48",
+ "upload_time_iso_8601":"2014-03-22T21:45:48.479439Z",
+ "url":"https://files.pythonhosted.org/packages/6d/00/46c60054e46e7dd3728c52a19b16dcedbec743612ca51a2e3297b3946655/celery-3.1.10.tar.gz"
+ }
+ ],
+ "3.1.11":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"338c5d39c0c1f46e8e3b6882cae2cc4f",
+ "sha256":"9154ba723a7486c003639932b8ec1a69d7dee6837110647a6077cc7ac501e15e"
+ },
+ "downloads":-1,
+ "filename":"celery-3.1.11-py27-none-any.whl",
+ "has_sig":true,
+ "md5_digest":"338c5d39c0c1f46e8e3b6882cae2cc4f",
+ "packagetype":"bdist_wheel",
+ "python_version":"2.7",
+ "requires_python":null,
+ "size":513865,
+ "upload_time":"2014-04-16T23:45:42",
+ "upload_time_iso_8601":"2014-04-16T23:45:42.996722Z",
+ "url":"https://files.pythonhosted.org/packages/f4/c4/63d760c4b578f3b82478af47696eb55ec03852a2ef8e17aa7c0426187adf/celery-3.1.11-py27-none-any.whl"
+ },
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"f7ae17cd1e21e391d970368f1fb6427e",
+ "sha256":"7614e789a997a540bab589ca763f1006c6881e64479e8a03f72b225c25ff5250"
+ },
+ "downloads":-1,
+ "filename":"celery-3.1.11.tar.gz",
+ "has_sig":true,
+ "md5_digest":"f7ae17cd1e21e391d970368f1fb6427e",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1289359,
+ "upload_time":"2014-04-16T23:44:59",
+ "upload_time_iso_8601":"2014-04-16T23:44:59.786853Z",
+ "url":"https://files.pythonhosted.org/packages/95/fa/7534da21cab73646d53211ebd620ade01317d08a2eb21a0801bbb2613695/celery-3.1.11.tar.gz"
+ }
+ ],
+ "3.1.12":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"16cbb616c5ece32eff74debda26caf4c",
+ "sha256":"211e6f3e9b9429831ebacca3be03c097eb75eb82ac6a00273269c30e41b8e839"
+ },
+ "downloads":-1,
+ "filename":"celery-3.1.12-py2.py3-none-any.whl",
+ "has_sig":true,
+ "md5_digest":"16cbb616c5ece32eff74debda26caf4c",
+ "packagetype":"bdist_wheel",
+ "python_version":"2.7",
+ "requires_python":null,
+ "size":513519,
+ "upload_time":"2014-06-09T22:16:51",
+ "upload_time_iso_8601":"2014-06-09T22:16:51.550111Z",
+ "url":"https://files.pythonhosted.org/packages/0f/2a/4888ef72f74c22729fa06cb8f7c60ad1f00f41cdd6d0e4237f119a234d38/celery-3.1.12-py2.py3-none-any.whl"
+ },
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"31927b26c3225fac0250ac4fe2849824",
+ "sha256":"22c8fba96b7522afacdf3ee6fd3da7b10b90f76de88686d13ee939da361254b1"
+ },
+ "downloads":-1,
+ "filename":"celery-3.1.12.tar.gz",
+ "has_sig":true,
+ "md5_digest":"31927b26c3225fac0250ac4fe2849824",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1291525,
+ "upload_time":"2014-06-09T22:16:03",
+ "upload_time_iso_8601":"2014-06-09T22:16:03.090357Z",
+ "url":"https://files.pythonhosted.org/packages/d0/bf/447ba1a5f6914722541dae537085c210ce0a0897638742facac99070732b/celery-3.1.12.tar.gz"
+ }
+ ],
+ "3.1.13":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"facd8c237e1b4e1185ebc1de6d1f8433",
+ "sha256":"38fbef3e6f5a8513f28d8c9f66be08a40d6784fa56f50ffe8de9926767c7032a"
+ },
+ "downloads":-1,
+ "filename":"celery-3.1.13-py2.py3-none-any.whl",
+ "has_sig":true,
+ "md5_digest":"facd8c237e1b4e1185ebc1de6d1f8433",
+ "packagetype":"bdist_wheel",
+ "python_version":"2.7",
+ "requires_python":null,
+ "size":513621,
+ "upload_time":"2014-07-10T21:11:14",
+ "upload_time_iso_8601":"2014-07-10T21:11:14.627413Z",
+ "url":"https://files.pythonhosted.org/packages/e9/ac/7ae35524916523726072361375c810c79b4976581a751431bd1cee1f5c04/celery-3.1.13-py2.py3-none-any.whl"
+ },
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"549aa12b13f77d1363e9087d3deb4742",
+ "sha256":"04b921326a64f17af5ba9c94e5189a498b36d8c01bebd215d12abeee0f55940c"
+ },
+ "downloads":-1,
+ "filename":"celery-3.1.13.tar.gz",
+ "has_sig":true,
+ "md5_digest":"549aa12b13f77d1363e9087d3deb4742",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1292738,
+ "upload_time":"2014-07-10T21:01:29",
+ "upload_time_iso_8601":"2014-07-10T21:01:29.239899Z",
+ "url":"https://files.pythonhosted.org/packages/0d/d7/197fee639c230eb8ec5d17f8388e99aa59fb1e71e8ea0496cb206849c964/celery-3.1.13.tar.gz"
+ }
+ ],
+ "3.1.14":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"c37b580b2827b4edb8e309c69faadd6b",
+ "sha256":"ab12d39a39af4bce3dadf520b6d73e044202bfc55ba670677718b5a8b967ae4f"
+ },
+ "downloads":-1,
+ "filename":"celery-3.1.14-py2.py3-none-any.whl",
+ "has_sig":true,
+ "md5_digest":"c37b580b2827b4edb8e309c69faadd6b",
+ "packagetype":"bdist_wheel",
+ "python_version":"2.7",
+ "requires_python":null,
+ "size":513922,
+ "upload_time":"2014-09-08T14:53:41",
+ "upload_time_iso_8601":"2014-09-08T14:53:41.374980Z",
+ "url":"https://files.pythonhosted.org/packages/8c/d4/19b76fb1f22c3a2d3e3cfc9ded52fdf952bec6566aacb0c407fd32b4c316/celery-3.1.14-py2.py3-none-any.whl"
+ },
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"9afdefe648ff12284c0beab8d9ce7f5a",
+ "sha256":"c6a72c73046560f58076e83cda6fb63b778bb379ffe07e01655a38e2f54c373c"
+ },
+ "downloads":-1,
+ "filename":"celery-3.1.14.tar.gz",
+ "has_sig":true,
+ "md5_digest":"9afdefe648ff12284c0beab8d9ce7f5a",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1295021,
+ "upload_time":"2014-09-08T14:53:29",
+ "upload_time_iso_8601":"2014-09-08T14:53:29.262056Z",
+ "url":"https://files.pythonhosted.org/packages/98/87/fbb1e7095c4a5e3cce4bf22c18ea32fa635877491418fa91cdb77cd2d447/celery-3.1.14.tar.gz"
+ }
+ ],
+ "3.1.15":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"434a911245b021a0af867f354ef4af31",
+ "sha256":"7111697b3332ac22dd7047d492d70218d0a8ee0aa24246f6aec44274692033aa"
+ },
+ "downloads":-1,
+ "filename":"celery-3.1.15-py2.py3-none-any.whl",
+ "has_sig":true,
+ "md5_digest":"434a911245b021a0af867f354ef4af31",
+ "packagetype":"bdist_wheel",
+ "python_version":"2.7",
+ "requires_python":null,
+ "size":513935,
+ "upload_time":"2014-09-14T23:28:59",
+ "upload_time_iso_8601":"2014-09-14T23:28:59.140361Z",
+ "url":"https://files.pythonhosted.org/packages/26/1d/09af39b4da466c93eab0cc9e0c0225764b619ce69fe0951d10a9ab04ffa3/celery-3.1.15-py2.py3-none-any.whl"
+ },
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"670382ef244228b645a91c65bc200ab4",
+ "sha256":"84715d0b9c76818af45f7eeba76532afddff2030a313beecd0e9e2eae4dbe9e3"
+ },
+ "downloads":-1,
+ "filename":"celery-3.1.15.tar.gz",
+ "has_sig":true,
+ "md5_digest":"670382ef244228b645a91c65bc200ab4",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1295292,
+ "upload_time":"2014-09-14T23:28:51",
+ "upload_time_iso_8601":"2014-09-14T23:28:51.166506Z",
+ "url":"https://files.pythonhosted.org/packages/a8/88/295ccc83ccc78c3f493a342a541e57ef48080fc489c0cb9b374a5afc34a0/celery-3.1.15.tar.gz"
+ }
+ ],
+ "3.1.16":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"498b515252b94dc69e7808e19ed38d88",
+ "sha256":"e84498376fb052415040696b79fb0f185e3c732729670109b4f1e2303be6c9f5"
+ },
+ "downloads":-1,
+ "filename":"celery-3.1.16-py2.py3-none-any.whl",
+ "has_sig":true,
+ "md5_digest":"498b515252b94dc69e7808e19ed38d88",
+ "packagetype":"bdist_wheel",
+ "python_version":"2.7",
+ "requires_python":null,
+ "size":514222,
+ "upload_time":"2014-10-03T22:36:35",
+ "upload_time_iso_8601":"2014-10-03T22:36:35.250138Z",
+ "url":"https://files.pythonhosted.org/packages/85/7f/0cd3d70eac0e022df72c4bd42a958b64ca0034b9469f0422aced56b5f368/celery-3.1.16-py2.py3-none-any.whl"
+ },
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"465f0b707886349eb9ec962dc866789d",
+ "sha256":"83079c2974b3e1ac7517b33cde829db59fc2f560482c85ee4f2c751d3dd4f8f3"
+ },
+ "downloads":-1,
+ "filename":"celery-3.1.16.tar.gz",
+ "has_sig":true,
+ "md5_digest":"465f0b707886349eb9ec962dc866789d",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1296002,
+ "upload_time":"2014-10-03T22:37:40",
+ "upload_time_iso_8601":"2014-10-03T22:37:40.682952Z",
+ "url":"https://files.pythonhosted.org/packages/2c/87/22c4cb487cdce239b1945507e5366d3c9074f94c61504b88e873a9474905/celery-3.1.16.tar.gz"
+ }
+ ],
+ "3.1.17":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"e0978680f5a340ce4d022897f3e43c42",
+ "sha256":"1743aa8689bd2867c5ab3af00a8742635eb560963b1b93e14cd22d66fb77e135"
+ },
+ "downloads":-1,
+ "filename":"celery-3.1.17-py2.py3-none-any.whl",
+ "has_sig":true,
+ "md5_digest":"e0978680f5a340ce4d022897f3e43c42",
+ "packagetype":"bdist_wheel",
+ "python_version":"2.7",
+ "requires_python":null,
+ "size":514940,
+ "upload_time":"2014-11-19T15:32:07",
+ "upload_time_iso_8601":"2014-11-19T15:32:07.401738Z",
+ "url":"https://files.pythonhosted.org/packages/12/28/0b6cfb91734fe3bbf57fea6e87d9796977c54f5c5640e87183a695f61118/celery-3.1.17-py2.py3-none-any.whl"
+ },
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"e37f5d93b960bf68fc26c1325f30fd16",
+ "sha256":"cfe2b653268bd586e2d08a75e886f7be3be55ba372f72e2f5747aeb76c470362"
+ },
+ "downloads":-1,
+ "filename":"celery-3.1.17.tar.gz",
+ "has_sig":true,
+ "md5_digest":"e37f5d93b960bf68fc26c1325f30fd16",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1297008,
+ "upload_time":"2014-11-19T15:31:59",
+ "upload_time_iso_8601":"2014-11-19T15:31:59.282605Z",
+ "url":"https://files.pythonhosted.org/packages/b5/2e/0c95c6b95d4d9fcb8b00bdc38921448570761b006aab0ed8380fd398ee28/celery-3.1.17.tar.gz"
+ }
+ ],
+ "3.1.18":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"692453eb7257cc7b70b538fb3fc2f395",
+ "sha256":"dbf59618d5a9eff172d25021f36614be5af0501e4527975ca504b95863f14fed"
+ },
+ "downloads":-1,
+ "filename":"celery-3.1.18-py2.py3-none-any.whl",
+ "has_sig":true,
+ "md5_digest":"692453eb7257cc7b70b538fb3fc2f395",
+ "packagetype":"bdist_wheel",
+ "python_version":"2.7",
+ "requires_python":null,
+ "size":515913,
+ "upload_time":"2015-04-22T17:47:41",
+ "upload_time_iso_8601":"2015-04-22T17:47:41.749180Z",
+ "url":"https://files.pythonhosted.org/packages/94/50/2b824c2a2b53a05763a71138fa494f913b272511ead9757522a9ab3c0077/celery-3.1.18-py2.py3-none-any.whl"
+ },
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"1c25973250f75788fb9c690d4fc68957",
+ "sha256":"0924f94070c6fc57d408b169848c5b38832668fffe060e48b4803fb23e0e3eaf"
+ },
+ "downloads":-1,
+ "filename":"celery-3.1.18.tar.gz",
+ "has_sig":true,
+ "md5_digest":"1c25973250f75788fb9c690d4fc68957",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1298756,
+ "upload_time":"2015-04-22T17:47:30",
+ "upload_time_iso_8601":"2015-04-22T17:47:30.221215Z",
+ "url":"https://files.pythonhosted.org/packages/2f/b9/8a5d74bb351c5082465aaddf8772cfe6d4e954da68f3ac0f79bfd48f22df/celery-3.1.18.tar.gz"
+ }
+ ],
+ "3.1.19":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"14b6cc4882dcc60252273e27c0a7650c",
+ "sha256":"434b4e62308428b0e83fbcd1cebb8853beb230237b1b23484063fcf1ff610b6e"
+ },
+ "downloads":-1,
+ "filename":"celery-3.1.19-py2.py3-none-any.whl",
+ "has_sig":true,
+ "md5_digest":"14b6cc4882dcc60252273e27c0a7650c",
+ "packagetype":"bdist_wheel",
+ "python_version":"2.7",
+ "requires_python":null,
+ "size":517433,
+ "upload_time":"2015-10-26T20:08:29",
+ "upload_time_iso_8601":"2015-10-26T20:08:29.530970Z",
+ "url":"https://files.pythonhosted.org/packages/55/e1/65d2b3ded641a5388055bdd8845a9a8e5b60e0bfd8280fc2bd85f931dc3a/celery-3.1.19-py2.py3-none-any.whl"
+ },
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"fba8c4b269814dc6dbc36abb0e66c384",
+ "sha256":"bd6a21290c822ecf78947a7dbc8b2270d88a5fa08a7a2bfcd908bb3d5ed66b71"
+ },
+ "downloads":-1,
+ "filename":"celery-3.1.19.tar.gz",
+ "has_sig":true,
+ "md5_digest":"fba8c4b269814dc6dbc36abb0e66c384",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1302241,
+ "upload_time":"2015-10-26T20:08:23",
+ "upload_time_iso_8601":"2015-10-26T20:08:23.990225Z",
+ "url":"https://files.pythonhosted.org/packages/f2/76/7178b22c4fb72575b31a62e223996b359c6630adaeb4ec283523dd35c430/celery-3.1.19.tar.gz"
+ }
+ ],
+ "3.1.2":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"3150cfee9a02edc2d0d4ad63f23dcb5b",
+ "sha256":"c07900e865ac54ba2baf5858acc55afb2ef5ec03d912691f1768a300ee57f5ba"
+ },
+ "downloads":-1,
+ "filename":"celery-3.1.2.tar.gz",
+ "has_sig":true,
+ "md5_digest":"3150cfee9a02edc2d0d4ad63f23dcb5b",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1269319,
+ "upload_time":"2013-11-12T20:14:47",
+ "upload_time_iso_8601":"2013-11-12T20:14:47.477871Z",
+ "url":"https://files.pythonhosted.org/packages/b3/5d/286b4b3fa243689302126f4314fde8cddfc16699d77c7a308e1cc57528f2/celery-3.1.2.tar.gz"
+ }
+ ],
+ "3.1.20":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"899b8fb9c042a56344e4a64c5fa8d05c",
+ "sha256":"3071b71ef8c43178ace8435002b11f2ff06db7690f07d960540eab7f4183ddf7"
+ },
+ "downloads":-1,
+ "filename":"celery-3.1.20-py2.py3-none-any.whl",
+ "has_sig":true,
+ "md5_digest":"899b8fb9c042a56344e4a64c5fa8d05c",
+ "packagetype":"bdist_wheel",
+ "python_version":"2.7",
+ "requires_python":null,
+ "size":518570,
+ "upload_time":"2016-01-23T02:48:30",
+ "upload_time_iso_8601":"2016-01-23T02:48:30.480767Z",
+ "url":"https://files.pythonhosted.org/packages/b9/ad/5233202888d305f7a5392a9c0729affe0b877168746ad4f666737750a10c/celery-3.1.20-py2.py3-none-any.whl"
+ },
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"025128230881de934461f1f2702ef721",
+ "sha256":"d02f191c3d92a851c9d2028e91baf2a0f2734cd3b659743d3624011d1ef7a6d5"
+ },
+ "downloads":-1,
+ "filename":"celery-3.1.20.tar.gz",
+ "has_sig":true,
+ "md5_digest":"025128230881de934461f1f2702ef721",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1308238,
+ "upload_time":"2016-01-23T02:48:18",
+ "upload_time_iso_8601":"2016-01-23T02:48:18.530241Z",
+ "url":"https://files.pythonhosted.org/packages/b2/67/ddda25b215d47d2e07617d0aa5ee95ab69feb5fee3319ba11a62fe14c17e/celery-3.1.20.tar.gz"
+ }
+ ],
+ "3.1.21":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"f20eef56635e8b0f34a1fa21a40ced04",
+ "sha256":"0d29beedd0805acea9c0f03d86194ec3e8ffa94e81034c083c1d3102079841f5"
+ },
+ "downloads":-1,
+ "filename":"celery-3.1.21-py2.py3-none-any.whl",
+ "has_sig":true,
+ "md5_digest":"f20eef56635e8b0f34a1fa21a40ced04",
+ "packagetype":"bdist_wheel",
+ "python_version":"2.7",
+ "requires_python":null,
+ "size":520206,
+ "upload_time":"2016-03-04T19:20:03",
+ "upload_time_iso_8601":"2016-03-04T19:20:03.449647Z",
+ "url":"https://files.pythonhosted.org/packages/07/07/f1269cb12a4644a428f35b8adfb764b9345dd7d5d3cec7f88222b20ab995/celery-3.1.21-py2.py3-none-any.whl"
+ },
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"27f313c7e4d0fb1bee0cd5f1decee180",
+ "sha256":"f7d0edfe85af73a16ab1c74975974e91a9f4cc48fe66bc3b46bcf3b9e103c746"
+ },
+ "downloads":-1,
+ "filename":"celery-3.1.21.tar.gz",
+ "has_sig":true,
+ "md5_digest":"27f313c7e4d0fb1bee0cd5f1decee180",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1310301,
+ "upload_time":"2016-03-04T19:19:50",
+ "upload_time_iso_8601":"2016-03-04T19:19:50.034184Z",
+ "url":"https://files.pythonhosted.org/packages/9c/d0/5b784a5846d8b44f90a40bc46f99203b708ab11d4f8e79f590defbff0116/celery-3.1.21.tar.gz"
+ }
+ ],
+ "3.1.22":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"11d441f8307bd67817e714f9aaf6d633",
+ "sha256":"4fd6fd2d096dcf2f0c19e0f15ea3520fd6a1f57a33791484edb0cf33495b9159"
+ },
+ "downloads":-1,
+ "filename":"celery-3.1.22-py2.py3-none-any.whl",
+ "has_sig":true,
+ "md5_digest":"11d441f8307bd67817e714f9aaf6d633",
+ "packagetype":"bdist_wheel",
+ "python_version":"2.7",
+ "requires_python":null,
+ "size":520385,
+ "upload_time":"2016-03-08T00:03:46",
+ "upload_time_iso_8601":"2016-03-08T00:03:46.862195Z",
+ "url":"https://files.pythonhosted.org/packages/5f/c7/7c904284a7d6f8caecf7b14354ed88f40ec76a451193aa626900c09ededa/celery-3.1.22-py2.py3-none-any.whl"
+ },
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"af6f4e529e80dbaa8f800192fba8f83f",
+ "sha256":"7e511421f967dee31756626e611d56aa1eb5b48383d3274f0a320b0254636a84"
+ },
+ "downloads":-1,
+ "filename":"celery-3.1.22.tar.gz",
+ "has_sig":true,
+ "md5_digest":"af6f4e529e80dbaa8f800192fba8f83f",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1310504,
+ "upload_time":"2016-03-08T00:03:25",
+ "upload_time_iso_8601":"2016-03-08T00:03:25.456393Z",
+ "url":"https://files.pythonhosted.org/packages/0f/9e/2af998899beb9cb27f201799b5b6d2ff13c0bebb61f151abf72f07a1158e/celery-3.1.22.tar.gz"
+ }
+ ],
+ "3.1.23":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"b2b5e20bd9042246f7b2c295d98315da",
+ "sha256":"eaf5dee3becbc35c7754a2d4482d53bdf72ea3f85dd258525259983262081474"
+ },
+ "downloads":-1,
+ "filename":"celery-3.1.23-py2.py3-none-any.whl",
+ "has_sig":true,
+ "md5_digest":"b2b5e20bd9042246f7b2c295d98315da",
+ "packagetype":"bdist_wheel",
+ "python_version":"2.7",
+ "requires_python":null,
+ "size":520409,
+ "upload_time":"2016-03-10T02:12:07",
+ "upload_time_iso_8601":"2016-03-10T02:12:07.628865Z",
+ "url":"https://files.pythonhosted.org/packages/de/df/59f5df67082ef46b86bc754b82f8cf187b835eea8a56ea8907813e75ad6d/celery-3.1.23-py2.py3-none-any.whl"
+ },
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"c6f10f956a49424d553ab1391ab39ab2",
+ "sha256":"1a359c815837f9dbf193a7dbc6addafa34612c077ff70c66e3b16e14eebd2418"
+ },
+ "downloads":-1,
+ "filename":"celery-3.1.23.tar.gz",
+ "has_sig":true,
+ "md5_digest":"c6f10f956a49424d553ab1391ab39ab2",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1310624,
+ "upload_time":"2016-03-10T02:11:51",
+ "upload_time_iso_8601":"2016-03-10T02:11:51.964658Z",
+ "url":"https://files.pythonhosted.org/packages/ea/a6/6da0bac3ea8abbc2763fd2664af2955702f97f140f2d7277069445532b7c/celery-3.1.23.tar.gz"
+ }
+ ],
+ "3.1.24":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"6d52079a2b15077b973823f1adb01e17",
+ "sha256":"25396191954521184cc15018f776a2a2278b04dd4213d94f795daef4b7961b4b"
+ },
+ "downloads":-1,
+ "filename":"celery-3.1.24-py2.py3-none-any.whl",
+ "has_sig":true,
+ "md5_digest":"6d52079a2b15077b973823f1adb01e17",
+ "packagetype":"bdist_wheel",
+ "python_version":"2.7",
+ "requires_python":null,
+ "size":526285,
+ "upload_time":"2016-10-01T00:18:42",
+ "upload_time_iso_8601":"2016-10-01T00:18:42.935217Z",
+ "url":"https://files.pythonhosted.org/packages/c8/82/f46379046f2150d92085c0814affb4bedbd1c7f9703e569c8575fd7f1a4f/celery-3.1.24-py2.py3-none-any.whl"
+ },
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"50a713dd38cf9b3574cb93745a467c59",
+ "sha256":"99b8085ff3013c8cebb9211857fadf5f402882ccada863d67c4d74db60be027a"
+ },
+ "downloads":-1,
+ "filename":"celery-3.1.24.tar.gz",
+ "has_sig":true,
+ "md5_digest":"50a713dd38cf9b3574cb93745a467c59",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1330180,
+ "upload_time":"2016-10-01T00:17:20",
+ "upload_time_iso_8601":"2016-10-01T00:17:20.814163Z",
+ "url":"https://files.pythonhosted.org/packages/dd/c0/f30014ce9426871010007e1994d3eaab8beb2929d4ca497456b7a97671fc/celery-3.1.24.tar.gz"
+ }
+ ],
+ "3.1.25":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"43b51c87cb22cf6cb94e68102481e139",
+ "sha256":"1954a224805f3835e5b6f5998ec9fe51db3413cc49e59fc720d314c7913427cf"
+ },
+ "downloads":-1,
+ "filename":"celery-3.1.25-py2.py3-none-any.whl",
+ "has_sig":true,
+ "md5_digest":"43b51c87cb22cf6cb94e68102481e139",
+ "packagetype":"bdist_wheel",
+ "python_version":"2.7",
+ "requires_python":null,
+ "size":526186,
+ "upload_time":"2016-11-05T01:51:13",
+ "upload_time_iso_8601":"2016-11-05T01:51:13.481247Z",
+ "url":"https://files.pythonhosted.org/packages/13/28/b45b7d4c13695f321522566747e0a4a9c8883515f664e0487974e5f79d16/celery-3.1.25-py2.py3-none-any.whl"
+ },
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"81ebed2cccbc03c2d8adcba4fefac3bb",
+ "sha256":"6ced63033bc663e60c992564954dbb5c84c43899f7f1a04b739957350f6b55f3"
+ },
+ "downloads":-1,
+ "filename":"celery-3.1.25.tar.gz",
+ "has_sig":true,
+ "md5_digest":"81ebed2cccbc03c2d8adcba4fefac3bb",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1330179,
+ "upload_time":"2016-11-05T01:52:13",
+ "upload_time_iso_8601":"2016-11-05T01:52:13.671524Z",
+ "url":"https://files.pythonhosted.org/packages/62/8d/5d9e8cddd987b409b9a332a5eb73c2d01ea42ab83865e8e8a011326c16dc/celery-3.1.25.tar.gz"
+ }
+ ],
+ "3.1.26-1":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"07ec6a80726a3625ed5ef6d5a6180156",
+ "sha256":"66ee284c8721fb64ed220f03c011955ce7530e87350b903fd4438e996afc0a94"
+ },
+ "downloads":-1,
+ "filename":"celery-3.1.26-1.tar.gz",
+ "has_sig":true,
+ "md5_digest":"07ec6a80726a3625ed5ef6d5a6180156",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":7703034,
+ "upload_time":"2018-03-24T09:29:54",
+ "upload_time_iso_8601":"2018-03-24T09:29:54.432606Z",
+ "url":"https://files.pythonhosted.org/packages/64/b8/1121f9a9fc30d267c877864b3d77a4f5309521c2e04b5d7ddf49b0096297/celery-3.1.26-1.tar.gz"
+ },
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"8dbeb133fc145dfdbb5d590f87930f53",
+ "sha256":"f546c07dfa7cd0d450ef0543ce6205a681923005c45dc7baeebfffc33ff671b2"
+ },
+ "downloads":-1,
+ "filename":"celery-3.1.26.post1-py2.py3-none-any.whl",
+ "has_sig":true,
+ "md5_digest":"8dbeb133fc145dfdbb5d590f87930f53",
+ "packagetype":"bdist_wheel",
+ "python_version":"py2.py3",
+ "requires_python":null,
+ "size":613613,
+ "upload_time":"2018-03-24T09:29:09",
+ "upload_time_iso_8601":"2018-03-24T09:29:09.639328Z",
+ "url":"https://files.pythonhosted.org/packages/a4/9a/3efa5da23cecc3f955c6ffbc78391b2e5a8befd766607fda6e6061daa9a5/celery-3.1.26.post1-py2.py3-none-any.whl"
+ }
+ ],
+ "3.1.26.post2":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"6ba493b09ba39e58074b19c38438a3bd",
+ "sha256":"60211897aee321266ff043fe2b33eaac825dfe9f46843cf964fc97507a186334"
+ },
+ "downloads":-1,
+ "filename":"celery-3.1.26.post2-py2.py3-none-any.whl",
+ "has_sig":true,
+ "md5_digest":"6ba493b09ba39e58074b19c38438a3bd",
+ "packagetype":"bdist_wheel",
+ "python_version":"py2.py3",
+ "requires_python":null,
+ "size":526344,
+ "upload_time":"2018-03-24T16:56:39",
+ "upload_time_iso_8601":"2018-03-24T16:56:39.954413Z",
+ "url":"https://files.pythonhosted.org/packages/b1/27/cd2e097208f60a0512b8b3201f8bd93c1db359c3fa35cab2f405aa1d45a7/celery-3.1.26.post2-py2.py3-none-any.whl"
+ },
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"a16881249d81591cdf5ce0dfb092ea80",
+ "sha256":"5493e172ae817b81ba7d09443ada114886765a8ce02f16a56e6fac68d953a9b2"
+ },
+ "downloads":-1,
+ "filename":"celery-3.1.26.post2.tar.gz",
+ "has_sig":true,
+ "md5_digest":"a16881249d81591cdf5ce0dfb092ea80",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1337633,
+ "upload_time":"2018-03-24T16:56:48",
+ "upload_time_iso_8601":"2018-03-24T16:56:48.602419Z",
+ "url":"https://files.pythonhosted.org/packages/33/f3/c6f66e311dd0be1eedcf6d256e4138caca537d81c1b903d4ab3699ada889/celery-3.1.26.post2.tar.gz"
+ }
+ ],
+ "3.1.3":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"e563897cde5ef792404bd09ff992b7aa",
+ "sha256":"902cf1ba70bbbc275c9d488355524627179d3d658afcf485c37ee0deea3a4ff5"
+ },
+ "downloads":-1,
+ "filename":"celery-3.1.3-py26-none-any.whl",
+ "has_sig":true,
+ "md5_digest":"e563897cde5ef792404bd09ff992b7aa",
+ "packagetype":"bdist_wheel",
+ "python_version":"2.6",
+ "requires_python":null,
+ "size":495576,
+ "upload_time":"2013-11-14T12:43:13",
+ "upload_time_iso_8601":"2013-11-14T12:43:13.539689Z",
+ "url":"https://files.pythonhosted.org/packages/51/d7/f06267f720bb3e24409ff0461253d71eeb186accea685053fda2a81c994f/celery-3.1.3-py26-none-any.whl"
+ },
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"161320e9eb166793afd44d54b19ca073",
+ "sha256":"ffce9982e27bbd37f76d862ef686be0b27c2ca936131e34a7fa9ebcd3c092d46"
+ },
+ "downloads":-1,
+ "filename":"celery-3.1.3-py27-none-any.whl",
+ "has_sig":true,
+ "md5_digest":"161320e9eb166793afd44d54b19ca073",
+ "packagetype":"bdist_wheel",
+ "python_version":"2.7",
+ "requires_python":null,
+ "size":492621,
+ "upload_time":"2013-11-14T12:41:49",
+ "upload_time_iso_8601":"2013-11-14T12:41:49.214591Z",
+ "url":"https://files.pythonhosted.org/packages/3d/dc/f624ebe7075e9c868b27229c396c45e8159569e1ebf76f1da3179dc452c4/celery-3.1.3-py27-none-any.whl"
+ },
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"291f2b3037c05085e02bf703a15b809b",
+ "sha256":"7c2849a89a88bc73dfb67c82574cb7f17d579756c1d16e849bee6156a91d3b7e"
+ },
+ "downloads":-1,
+ "filename":"celery-3.1.3-py33-none-any.whl",
+ "has_sig":true,
+ "md5_digest":"291f2b3037c05085e02bf703a15b809b",
+ "packagetype":"bdist_wheel",
+ "python_version":"3.3",
+ "requires_python":null,
+ "size":495578,
+ "upload_time":"2013-11-14T12:44:12",
+ "upload_time_iso_8601":"2013-11-14T12:44:12.424196Z",
+ "url":"https://files.pythonhosted.org/packages/f9/e3/385b465e50d38f1d50a9001c3825ed99da0e548e9a4873483b23e47f8216/celery-3.1.3-py33-none-any.whl"
+ },
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"a8f95994762ed63e7f04e1ea572cdd47",
+ "sha256":"767380e32547d5ec2d9a915f28708d4fb65a55c6c910d0ec717e1d08470d1d1c"
+ },
+ "downloads":-1,
+ "filename":"celery-3.1.3.tar.gz",
+ "has_sig":true,
+ "md5_digest":"a8f95994762ed63e7f04e1ea572cdd47",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1269548,
+ "upload_time":"2013-11-13T00:53:34",
+ "upload_time_iso_8601":"2013-11-13T00:53:34.686525Z",
+ "url":"https://files.pythonhosted.org/packages/e4/78/8ab04c00f49b4a8ddc788710e45dde020dad9c5f86fcb67c77725f0dbc28/celery-3.1.3.tar.gz"
+ }
+ ],
+ "3.1.4":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"60aa694cb6542ebb43a417f4005c4dfc",
+ "sha256":"8e2d1e1599426db1a555cd0148567b7549dd66144dbed88244d4dcb2443b8cbc"
+ },
+ "downloads":-1,
+ "filename":"celery-3.1.4.tar.gz",
+ "has_sig":true,
+ "md5_digest":"60aa694cb6542ebb43a417f4005c4dfc",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1270322,
+ "upload_time":"2013-11-16T00:15:54",
+ "upload_time_iso_8601":"2013-11-16T00:15:54.547740Z",
+ "url":"https://files.pythonhosted.org/packages/50/dd/8fe90a0d421388e5097e6bccaa82d69f0b1f6fa6ea4f8a7cd6cff1e642c4/celery-3.1.4.tar.gz"
+ }
+ ],
+ "3.1.5":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"a8ff438460e562d21dd762cbba7bb6e2",
+ "sha256":"56797e4ab88c702e2a2a25002b2c38ba2fa183270fe3db843f2f72943e4406df"
+ },
+ "downloads":-1,
+ "filename":"celery-3.1.5.tar.gz",
+ "has_sig":true,
+ "md5_digest":"a8ff438460e562d21dd762cbba7bb6e2",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1262355,
+ "upload_time":"2013-11-21T18:31:51",
+ "upload_time_iso_8601":"2013-11-21T18:31:51.867814Z",
+ "url":"https://files.pythonhosted.org/packages/f1/9e/15df5bc43eb89203a08073f60ce25ff8268a9236247e04a908627ac7d614/celery-3.1.5.tar.gz"
+ }
+ ],
+ "3.1.6":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"00eebe44a44fe060c7cd184d15ae0bd9",
+ "sha256":"320708cc2fb1cd1ca552330bb9c326c927668de1fee3b1e53ac6245e53d79e95"
+ },
+ "downloads":-1,
+ "filename":"celery-3.1.6.tar.gz",
+ "has_sig":true,
+ "md5_digest":"00eebe44a44fe060c7cd184d15ae0bd9",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1264225,
+ "upload_time":"2013-12-02T18:06:20",
+ "upload_time_iso_8601":"2013-12-02T18:06:20.012446Z",
+ "url":"https://files.pythonhosted.org/packages/00/ee/2a47b9e710e7e6d19a0197be214b6c044c40e055f2cbdd4c86ce0158d660/celery-3.1.6.tar.gz"
+ }
+ ],
+ "3.1.7":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"63a452d4338372d0a22de1961130907e",
+ "sha256":"4a46dd4eba08831605d0373d9f90c150580ab0bd0a5e50021baef16403d06304"
+ },
+ "downloads":-1,
+ "filename":"celery-3.1.7.tar.gz",
+ "has_sig":true,
+ "md5_digest":"63a452d4338372d0a22de1961130907e",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1271174,
+ "upload_time":"2013-12-17T18:08:01",
+ "upload_time_iso_8601":"2013-12-17T18:08:01.768105Z",
+ "url":"https://files.pythonhosted.org/packages/0c/62/6c20da627bdc4a48dbc27dc9d986ac13268999b043a5e4b3e8aacd200db2/celery-3.1.7.tar.gz"
+ }
+ ],
+ "3.1.8":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"a5631b69adde9e7c7af22f8ee2fd57e0",
+ "sha256":"0786c9aa2e1656baa96f8816a2a41886a49edd3e928f93f83b2820b2a072bbb9"
+ },
+ "downloads":-1,
+ "filename":"celery-3.1.8.tar.gz",
+ "has_sig":true,
+ "md5_digest":"a5631b69adde9e7c7af22f8ee2fd57e0",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1276228,
+ "upload_time":"2014-01-17T22:48:45",
+ "upload_time_iso_8601":"2014-01-17T22:48:45.094907Z",
+ "url":"https://files.pythonhosted.org/packages/5a/f9/7c7b3b1952151986544747e9c5de5f629c3d4bb3fd233c29dfaa0b7fbb33/celery-3.1.8.tar.gz"
+ }
+ ],
+ "3.1.9":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"6a39de14825619b10fa1af4c989af44b",
+ "sha256":"804daff247c9aa63ca3aeab95d49eb5c1f17441652db911e8219e92ae2b9d354"
+ },
+ "downloads":-1,
+ "filename":"celery-3.1.9-py27-none-any.whl",
+ "has_sig":true,
+ "md5_digest":"6a39de14825619b10fa1af4c989af44b",
+ "packagetype":"bdist_wheel",
+ "python_version":"2.7",
+ "requires_python":null,
+ "size":508152,
+ "upload_time":"2014-02-10T18:45:44",
+ "upload_time_iso_8601":"2014-02-10T18:45:44.074669Z",
+ "url":"https://files.pythonhosted.org/packages/7a/9c/c1f6ce0d80b8f7ee2eeb36bf9437a9b3f1c4edc4d3c37b9806ecd0c04426/celery-3.1.9-py27-none-any.whl"
+ },
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"5742a95c0bb07cc5159216aae3b025fb",
+ "sha256":"4a9ee7e7c4928577368187c4a1006a7e0755106fe83bac2de14971abe7ddfc2c"
+ },
+ "downloads":-1,
+ "filename":"celery-3.1.9.tar.gz",
+ "has_sig":true,
+ "md5_digest":"5742a95c0bb07cc5159216aae3b025fb",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1280858,
+ "upload_time":"2014-02-10T18:45:41",
+ "upload_time_iso_8601":"2014-02-10T18:45:41.034999Z",
+ "url":"https://files.pythonhosted.org/packages/cd/64/8499d48b0a147ca62ab95019506424f4af620de11c04b003912ff98ca0f2/celery-3.1.9.tar.gz"
+ }
+ ],
+ "4.0.0":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"21ba26ac8d5cd7af8fc8eb89ffca1edc",
+ "sha256":"ede3c75b205560000403a8e5f0c73f201779e669a1c45b42c69294bd6d4951bc"
+ },
+ "downloads":-1,
+ "filename":"celery-4.0.0-py2.py3-none-any.whl",
+ "has_sig":true,
+ "md5_digest":"21ba26ac8d5cd7af8fc8eb89ffca1edc",
+ "packagetype":"bdist_wheel",
+ "python_version":"2.7",
+ "requires_python":null,
+ "size":395281,
+ "upload_time":"2016-11-04T20:56:14",
+ "upload_time_iso_8601":"2016-11-04T20:56:14.925104Z",
+ "url":"https://files.pythonhosted.org/packages/4b/19/745db97793f786644df142f059beea7c784fa3e856758bb5c18891004d49/celery-4.0.0-py2.py3-none-any.whl"
+ },
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"a4407621012e759ebd62368309b12145",
+ "sha256":"3e38a9a7f2868f774dffbb49e3afd2e56f57875deb06cb3ee3808f572601a8f0"
+ },
+ "downloads":-1,
+ "filename":"celery-4.0.0.tar.gz",
+ "has_sig":true,
+ "md5_digest":"a4407621012e759ebd62368309b12145",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1319440,
+ "upload_time":"2016-11-04T20:56:10",
+ "upload_time_iso_8601":"2016-11-04T20:56:10.321081Z",
+ "url":"https://files.pythonhosted.org/packages/47/a6/1b5f1cc0a720ef17abd4ab4ee47e769d6bd4bad38b5b7fec3248ff33b4fc/celery-4.0.0.tar.gz"
+ }
+ ],
+ "4.0.0rc3":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"674569d86ff5a61d68f953924e7095b3",
+ "sha256":"5fd54f075d98bb9a226b594d1d9ef18b2f56e1981bdfa4f2bab999bd601544a9"
+ },
+ "downloads":-1,
+ "filename":"celery-4.0.0rc3-py2.py3-none-any.whl",
+ "has_sig":true,
+ "md5_digest":"674569d86ff5a61d68f953924e7095b3",
+ "packagetype":"bdist_wheel",
+ "python_version":"2.7",
+ "requires_python":null,
+ "size":553447,
+ "upload_time":"2016-07-08T22:31:58",
+ "upload_time_iso_8601":"2016-07-08T22:31:58.737265Z",
+ "url":"https://files.pythonhosted.org/packages/33/00/c8979f8302cf1ff31bbab31ac328073f0c23f49cf3d55cb2c5d67ed76954/celery-4.0.0rc3-py2.py3-none-any.whl"
+ },
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"7e81b659a3beffeadace397694f1dfe8",
+ "sha256":"3f108e0801fd4b5f7c98ec23c046b8d0585a15b7c9b1f907ea7b2c38b97684d1"
+ },
+ "downloads":-1,
+ "filename":"celery-4.0.0rc3.tar.gz",
+ "has_sig":true,
+ "md5_digest":"7e81b659a3beffeadace397694f1dfe8",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1347201,
+ "upload_time":"2016-07-08T22:31:52",
+ "upload_time_iso_8601":"2016-07-08T22:31:52.974580Z",
+ "url":"https://files.pythonhosted.org/packages/0c/4e/be8d89c18693ee8c5edb6a59c84ac77891b15a75a9cd0d5d70dfaa106d81/celery-4.0.0rc3.tar.gz"
+ }
+ ],
+ "4.0.0rc4":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"f135366bcfa9bd81d5f321cea77860a9",
+ "sha256":"afe08e3f67984b8f4e64f263beb9aab6bb3b6eb2d71965db1e6328bd8f290bea"
+ },
+ "downloads":-1,
+ "filename":"celery-4.0.0rc4-py2.py3-none-any.whl",
+ "has_sig":true,
+ "md5_digest":"f135366bcfa9bd81d5f321cea77860a9",
+ "packagetype":"bdist_wheel",
+ "python_version":"2.7",
+ "requires_python":null,
+ "size":392195,
+ "upload_time":"2016-09-08T22:30:45",
+ "upload_time_iso_8601":"2016-09-08T22:30:45.538069Z",
+ "url":"https://files.pythonhosted.org/packages/c2/22/a526c291b39542c8110df5f53973169897b83e96051a0a888b4fc6e8af94/celery-4.0.0rc4-py2.py3-none-any.whl"
+ },
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"b88a34a9710e0ad576d6a23e40e28e7a",
+ "sha256":"142e6a3c7c119f1adf82abf384cb9cadccd9b84b34515e3a128c2400adc6e38c"
+ },
+ "downloads":-1,
+ "filename":"celery-4.0.0rc4.tar.gz",
+ "has_sig":true,
+ "md5_digest":"b88a34a9710e0ad576d6a23e40e28e7a",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1393289,
+ "upload_time":"2016-09-08T22:30:40",
+ "upload_time_iso_8601":"2016-09-08T22:30:40.665167Z",
+ "url":"https://files.pythonhosted.org/packages/d2/5a/769c88e59712154a257efa187abbcd8344d627f9b18d06562569820c19e0/celery-4.0.0rc4.tar.gz"
+ }
+ ],
+ "4.0.0rc5":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"1819d7e6b7f34911bdf8589e96d91bd4",
+ "sha256":"7ba32f126a1e33c00adf55814e7725335ca00ddc7da170e2f0ea350d07ea5f99"
+ },
+ "downloads":-1,
+ "filename":"celery-4.0.0rc5-py2.py3-none-any.whl",
+ "has_sig":true,
+ "md5_digest":"1819d7e6b7f34911bdf8589e96d91bd4",
+ "packagetype":"bdist_wheel",
+ "python_version":"2.7",
+ "requires_python":null,
+ "size":402434,
+ "upload_time":"2016-10-15T01:07:12",
+ "upload_time_iso_8601":"2016-10-15T01:07:12.600662Z",
+ "url":"https://files.pythonhosted.org/packages/3c/19/7176f49b519ebf1d43ad048c4484e927964d70997d667296bfbbf7c87cf2/celery-4.0.0rc5-py2.py3-none-any.whl"
+ },
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"e9dc8284b060c79323dd059e3137f283",
+ "sha256":"1d6b819a1454eb641e4ca2c212038e79697c5ad2cb67d613dc56c8a64130dc82"
+ },
+ "downloads":-1,
+ "filename":"celery-4.0.0rc5.tar.gz",
+ "has_sig":true,
+ "md5_digest":"e9dc8284b060c79323dd059e3137f283",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1406534,
+ "upload_time":"2016-10-15T01:07:08",
+ "upload_time_iso_8601":"2016-10-15T01:07:08.568657Z",
+ "url":"https://files.pythonhosted.org/packages/6d/5a/5075c6a3eca3120d41916014d281f71c4109427c53ff34f5728ae9f07148/celery-4.0.0rc5.tar.gz"
+ }
+ ],
+ "4.0.0rc6":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"6911ddb9057ed4d992d41fe97ed03ed5",
+ "sha256":"cded408aa194919dd169037ca64a3c3c944922d4b438f447f5073d0ff9129a88"
+ },
+ "downloads":-1,
+ "filename":"celery-4.0.0rc6-py2.py3-none-any.whl",
+ "has_sig":true,
+ "md5_digest":"6911ddb9057ed4d992d41fe97ed03ed5",
+ "packagetype":"bdist_wheel",
+ "python_version":"2.7",
+ "requires_python":null,
+ "size":413338,
+ "upload_time":"2016-10-22T02:42:31",
+ "upload_time_iso_8601":"2016-10-22T02:42:31.486695Z",
+ "url":"https://files.pythonhosted.org/packages/75/1d/1ca75e00cb5f9d6a86385a3575305d94e6980bc606aa94673035a708dcbc/celery-4.0.0rc6-py2.py3-none-any.whl"
+ },
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"1658210588996c839146308a3e7c4ade",
+ "sha256":"50f1dd544f2b956f88f9139d707f5909d8ade3dd87e93fc372b1a00d5b180e9c"
+ },
+ "downloads":-1,
+ "filename":"celery-4.0.0rc6.tar.gz",
+ "has_sig":true,
+ "md5_digest":"1658210588996c839146308a3e7c4ade",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1419750,
+ "upload_time":"2016-10-22T02:42:26",
+ "upload_time_iso_8601":"2016-10-22T02:42:26.710001Z",
+ "url":"https://files.pythonhosted.org/packages/e4/88/d52ef385e787906d40d13569eac379878d3fa2c9c37fa125c9328fd8b26f/celery-4.0.0rc6.tar.gz"
+ }
+ ],
+ "4.0.0rc7":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"e00e5756704a487466753acb4172db20",
+ "sha256":"85794207656d4cabdf6204142438c91ce6f3a51144561a4b163e582ec096a845"
+ },
+ "downloads":-1,
+ "filename":"celery-4.0.0rc7-py2.py3-none-any.whl",
+ "has_sig":true,
+ "md5_digest":"e00e5756704a487466753acb4172db20",
+ "packagetype":"bdist_wheel",
+ "python_version":"2.7",
+ "requires_python":null,
+ "size":419550,
+ "upload_time":"2016-11-03T00:55:45",
+ "upload_time_iso_8601":"2016-11-03T00:55:45.685897Z",
+ "url":"https://files.pythonhosted.org/packages/1e/64/083e7d1a29a01044b5f2b8a8854bfaa1d80c8e4ed96a7774375098a74445/celery-4.0.0rc7-py2.py3-none-any.whl"
+ },
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"094446dc56da00114ee7892888fe4020",
+ "sha256":"5e5e8180a18baea747bfec842771a1249b678190eb80eb9362710e44b2f3fd66"
+ },
+ "downloads":-1,
+ "filename":"celery-4.0.0rc7.tar.gz",
+ "has_sig":true,
+ "md5_digest":"094446dc56da00114ee7892888fe4020",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1431962,
+ "upload_time":"2016-11-03T00:55:39",
+ "upload_time_iso_8601":"2016-11-03T00:55:39.196050Z",
+ "url":"https://files.pythonhosted.org/packages/45/62/5db583643853696be9ef10a87bbec327f3f3e305929677a8b447b20f958e/celery-4.0.0rc7.tar.gz"
+ }
+ ],
+ "4.0.1":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"9cb21647de9da1136a7aa38376ba6dd1",
+ "sha256":"a09f6d123794fc3a51dcd1545793333b2167889439012fa5ef82821b4af42163"
+ },
+ "downloads":-1,
+ "filename":"celery-4.0.1-py2.py3-none-any.whl",
+ "has_sig":true,
+ "md5_digest":"9cb21647de9da1136a7aa38376ba6dd1",
+ "packagetype":"bdist_wheel",
+ "python_version":"2.7",
+ "requires_python":null,
+ "size":396380,
+ "upload_time":"2016-12-09T01:36:00",
+ "upload_time_iso_8601":"2016-12-09T01:36:00.840154Z",
+ "url":"https://files.pythonhosted.org/packages/81/d5/5fb88ee70cf91d83659cfe88e997d2b5a665455b04b656840b4179c61900/celery-4.0.1-py2.py3-none-any.whl"
+ },
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"addf3afad2808cab1a4175f5dce9e221",
+ "sha256":"763b28532c8ee2fa8c86ff1d721bfbf858550e24366e40871e5ec4d06252cb46"
+ },
+ "downloads":-1,
+ "filename":"celery-4.0.1.tar.gz",
+ "has_sig":true,
+ "md5_digest":"addf3afad2808cab1a4175f5dce9e221",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1336892,
+ "upload_time":"2016-12-09T01:35:56",
+ "upload_time_iso_8601":"2016-12-09T01:35:56.918591Z",
+ "url":"https://files.pythonhosted.org/packages/dd/fe/a44bd232539369977898b791f5f6f37be87f56872f9feb24b5c4e10a5213/celery-4.0.1.tar.gz"
+ }
+ ],
+ "4.0.2":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"3ff97b53107b491baeb42f662be14a06",
+ "sha256":"0e5b7e0d7f03aa02061abfd27aa9da05b6740281ca1f5228a54fbf7fe74d8afa"
+ },
+ "downloads":-1,
+ "filename":"celery-4.0.2-py2.py3-none-any.whl",
+ "has_sig":true,
+ "md5_digest":"3ff97b53107b491baeb42f662be14a06",
+ "packagetype":"bdist_wheel",
+ "python_version":"2.7",
+ "requires_python":null,
+ "size":396437,
+ "upload_time":"2016-12-16T00:14:59",
+ "upload_time_iso_8601":"2016-12-16T00:14:59.677799Z",
+ "url":"https://files.pythonhosted.org/packages/11/46/3524d4730d3217960b5e32cb8b202420af8714e2b123b9f95882e1fb2067/celery-4.0.2-py2.py3-none-any.whl"
+ },
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"364dbf014ad57a6aa60d823670642e5d",
+ "sha256":"e3d5a6c56a73ff8f2ddd4d06dc37f4c2afe4bb4da7928b884d0725ea865ef54d"
+ },
+ "downloads":-1,
+ "filename":"celery-4.0.2.tar.gz",
+ "has_sig":true,
+ "md5_digest":"364dbf014ad57a6aa60d823670642e5d",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1337804,
+ "upload_time":"2016-12-16T00:14:42",
+ "upload_time_iso_8601":"2016-12-16T00:14:42.864636Z",
+ "url":"https://files.pythonhosted.org/packages/b2/b7/888565f3e955473247aef86174db5121d16de6661b69bd8f3d10aff574f6/celery-4.0.2.tar.gz"
+ }
+ ],
+ "4.1.0":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"647073f137121298d1916b09b9560b4c",
+ "sha256":"81a67f0d53a688ec2bc8557bd5d6d7218f925a6f2e6df80e01560de9e28997ec"
+ },
+ "downloads":-1,
+ "filename":"celery-4.1.0-py2.py3-none-any.whl",
+ "has_sig":true,
+ "md5_digest":"647073f137121298d1916b09b9560b4c",
+ "packagetype":"bdist_wheel",
+ "python_version":"py2.py3",
+ "requires_python":null,
+ "size":400373,
+ "upload_time":"2017-07-24T17:23:13",
+ "upload_time_iso_8601":"2017-07-24T17:23:13.472944Z",
+ "url":"https://files.pythonhosted.org/packages/22/9b/88ef5cc7edf5d43215f383ae0a2b1cdeb33f5f07886386c7e4691b2eba0c/celery-4.1.0-py2.py3-none-any.whl"
+ },
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"db91e1d26936381127f01e150fe3054a",
+ "sha256":"77ff3730198d6a17b3c1f05579ebe570b579efb35f6d7e13dba3b1368d068b35"
+ },
+ "downloads":-1,
+ "filename":"celery-4.1.0.tar.gz",
+ "has_sig":true,
+ "md5_digest":"db91e1d26936381127f01e150fe3054a",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1331689,
+ "upload_time":"2017-07-24T17:23:19",
+ "upload_time_iso_8601":"2017-07-24T17:23:19.732941Z",
+ "url":"https://files.pythonhosted.org/packages/07/65/88a2a45fc80f487872c93121a701a53bbbc3d3d832016876fac84fc8d46a/celery-4.1.0.tar.gz"
+ }
+ ],
+ "4.1.1":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"544f0c7bcb465b3f94ddd649332730f9",
+ "sha256":"6fc4678d1692af97e137b2a9f1c04efd8e7e2fb7134c5c5ad60738cdd927762f"
+ },
+ "downloads":-1,
+ "filename":"celery-4.1.1-py2.py3-none-any.whl",
+ "has_sig":true,
+ "md5_digest":"544f0c7bcb465b3f94ddd649332730f9",
+ "packagetype":"bdist_wheel",
+ "python_version":"py2.py3",
+ "requires_python":null,
+ "size":394706,
+ "upload_time":"2018-05-21T09:47:24",
+ "upload_time_iso_8601":"2018-05-21T09:47:24.506769Z",
+ "url":"https://files.pythonhosted.org/packages/99/fa/4049b26bfe71992ecf979acd39b87e55b493608613054089d975418015b7/celery-4.1.1-py2.py3-none-any.whl"
+ },
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"9f807beea25be96647d75bbcad9d4d5d",
+ "sha256":"d1f2a3359bdbdfb344edce98b8e891f5fe64f8a11c5a45538ec20ac237c971f5"
+ },
+ "downloads":-1,
+ "filename":"celery-4.1.1.tar.gz",
+ "has_sig":true,
+ "md5_digest":"9f807beea25be96647d75bbcad9d4d5d",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":null,
+ "size":1332173,
+ "upload_time":"2018-05-21T09:47:30",
+ "upload_time_iso_8601":"2018-05-21T09:47:30.333491Z",
+ "url":"https://files.pythonhosted.org/packages/e9/cf/a4c0597effca20c57eb586324e41d1180bc8f13a933da41e0646cff69f02/celery-4.1.1.tar.gz"
+ }
+ ],
+ "4.2.0":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"f44208cefca2c357e1539fd900523a2d",
+ "sha256":"2082cbd82effa8ac8a8a58977d70bb203a9f362817e3b66f4578117b9f93d8a9"
+ },
+ "downloads":-1,
+ "filename":"celery-4.2.0-py2.py3-none-any.whl",
+ "has_sig":true,
+ "md5_digest":"f44208cefca2c357e1539fd900523a2d",
+ "packagetype":"bdist_wheel",
+ "python_version":"py2.py3",
+ "requires_python":">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size":401245,
+ "upload_time":"2018-06-10T18:28:09",
+ "upload_time_iso_8601":"2018-06-10T18:28:09.571847Z",
+ "url":"https://files.pythonhosted.org/packages/ea/75/d7d1eaeb6c90c7442f7b96242a6d4ebcf1cf075f9c51957d061fb8264d24/celery-4.2.0-py2.py3-none-any.whl"
+ },
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"d38a462edbe08d68f9965e6948666a9e",
+ "sha256":"ff727c115533edbc7b81b2b4ba1ec88d1c2fc4836e1e2f4c3c33a76ff53e5d7f"
+ },
+ "downloads":-1,
+ "filename":"celery-4.2.0.tar.gz",
+ "has_sig":true,
+ "md5_digest":"d38a462edbe08d68f9965e6948666a9e",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size":1351778,
+ "upload_time":"2018-06-10T18:29:18",
+ "upload_time_iso_8601":"2018-06-10T18:29:18.646209Z",
+ "url":"https://files.pythonhosted.org/packages/78/e1/93388de1535bfd7eb65bddda361dcb482a84d373d7c81f8d8d2172caf664/celery-4.2.0.tar.gz"
+ }
+ ],
+ "4.2.0rc1":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"f57dc80bf33a1150f6672cf9a73ecede",
+ "sha256":"1d721d00374b037ce2db791be43283638d4dd93ab9c306093475542a3f30bd28"
+ },
+ "downloads":-1,
+ "filename":"celery-4.2.0rc1-py2.py3-none-any.whl",
+ "has_sig":true,
+ "md5_digest":"f57dc80bf33a1150f6672cf9a73ecede",
+ "packagetype":"bdist_wheel",
+ "python_version":"py2.py3",
+ "requires_python":">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size":639349,
+ "upload_time":"2018-03-23T15:40:34",
+ "upload_time_iso_8601":"2018-03-23T15:40:34.703528Z",
+ "url":"https://files.pythonhosted.org/packages/7e/c3/4e032b12e2015b4dfa7c510cd2d3217e9b24d6f9c8842e14d7d747de8e63/celery-4.2.0rc1-py2.py3-none-any.whl"
+ },
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"fdceb00b60b8df5a43572e849f4e0a85",
+ "sha256":"ce8cf9010fa399eca159f46a5b6163574c414c30e2ebc8a0a2f805f81b879bcd"
+ },
+ "downloads":-1,
+ "filename":"celery-4.2.0rc1.tar.gz",
+ "has_sig":true,
+ "md5_digest":"fdceb00b60b8df5a43572e849f4e0a85",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size":1345375,
+ "upload_time":"2018-03-23T15:40:40",
+ "upload_time_iso_8601":"2018-03-23T15:40:40.576249Z",
+ "url":"https://files.pythonhosted.org/packages/53/1f/930018759182291c23b8c08e799d5e75466d532b68386a85c09ba6e12e6b/celery-4.2.0rc1.tar.gz"
+ }
+ ],
+ "4.2.0rc2":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"d48583af98eecf9e760b52313512f453",
+ "sha256":"4f5f6e18f0055efc0c3deccb01fa67e458acb1e4e0be495cfa2e7e4ea5f62751"
+ },
+ "downloads":-1,
+ "filename":"celery-4.2.0rc2-py2.py3-none-any.whl",
+ "has_sig":true,
+ "md5_digest":"d48583af98eecf9e760b52313512f453",
+ "packagetype":"bdist_wheel",
+ "python_version":"py2.py3",
+ "requires_python":">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size":406512,
+ "upload_time":"2018-04-02T08:29:27",
+ "upload_time_iso_8601":"2018-04-02T08:29:27.174294Z",
+ "url":"https://files.pythonhosted.org/packages/46/ec/1b77aef19695154dba004aceb4d50b32f36f6cc2832557514fe1f8d08aee/celery-4.2.0rc2-py2.py3-none-any.whl"
+ },
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"d735da3d70808ca554ef5b8cf1f27e80",
+ "sha256":"c82f7531056b7193b8218c32a6cbdf9057782b45cd305ad98388b4b0aa2598d0"
+ },
+ "downloads":-1,
+ "filename":"celery-4.2.0rc2.tar.gz",
+ "has_sig":true,
+ "md5_digest":"d735da3d70808ca554ef5b8cf1f27e80",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size":1345823,
+ "upload_time":"2018-04-02T08:29:32",
+ "upload_time_iso_8601":"2018-04-02T08:29:32.984984Z",
+ "url":"https://files.pythonhosted.org/packages/83/86/fc97823f2d132c6428e70ab042dc54b88f147e017d5eed70e207979bb477/celery-4.2.0rc2.tar.gz"
+ }
+ ],
+ "4.2.0rc3":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"cca7c246dbee5dc3038de6992694b9a8",
+ "sha256":"09c28887cf6136d3473410a724fd94f2d3107498fe536c9be95b5e0b48e549dd"
+ },
+ "downloads":-1,
+ "filename":"celery-4.2.0rc3-py2.py3-none-any.whl",
+ "has_sig":true,
+ "md5_digest":"cca7c246dbee5dc3038de6992694b9a8",
+ "packagetype":"bdist_wheel",
+ "python_version":"py2.py3",
+ "requires_python":">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size":406220,
+ "upload_time":"2018-04-29T06:29:31",
+ "upload_time_iso_8601":"2018-04-29T06:29:31.463396Z",
+ "url":"https://files.pythonhosted.org/packages/ec/4b/cbaab09d1601273ba750d224109eb2a661413922f6ef088b1248e5094ad8/celery-4.2.0rc3-py2.py3-none-any.whl"
+ },
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"dc503f414c51d2fc4c38cad9de9d695a",
+ "sha256":"a7a5adfcd5c9a1deec7772f06218b96440dd6ebc0abc8e586933813ece07f230"
+ },
+ "downloads":-1,
+ "filename":"celery-4.2.0rc3.tar.gz",
+ "has_sig":true,
+ "md5_digest":"dc503f414c51d2fc4c38cad9de9d695a",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size":1346934,
+ "upload_time":"2018-04-29T06:29:37",
+ "upload_time_iso_8601":"2018-04-29T06:29:37.976014Z",
+ "url":"https://files.pythonhosted.org/packages/4f/5d/13bde750045f4519f4dfc2a1fae7a714dcbc8ffa98c711ce14bc044452d5/celery-4.2.0rc3.tar.gz"
+ }
+ ],
+ "4.2.0rc4":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"022728f7f9fb35e829e55fa06469b343",
+ "sha256":"22dc3b5a43f6d2ca127d976009357684a6e0671577987193695222936ac0a6dd"
+ },
+ "downloads":-1,
+ "filename":"celery-4.2.0rc4-py2.py3-none-any.whl",
+ "has_sig":true,
+ "md5_digest":"022728f7f9fb35e829e55fa06469b343",
+ "packagetype":"bdist_wheel",
+ "python_version":"py2.py3",
+ "requires_python":">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size":401047,
+ "upload_time":"2018-05-22T06:25:30",
+ "upload_time_iso_8601":"2018-05-22T06:25:30.933123Z",
+ "url":"https://files.pythonhosted.org/packages/e3/3b/411ae267bbb10a1ea8d7ab79ec6be0f2530a4a9ae977e35afa5879c76d89/celery-4.2.0rc4-py2.py3-none-any.whl"
+ },
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"1e0dc70edc40ff7bff6f8f7c6cd3fbbc",
+ "sha256":"68291fb53ec47600fb7c0ec5def6d631fd0f0a0f37fb2c4a050e56e5794cc9e5"
+ },
+ "downloads":-1,
+ "filename":"celery-4.2.0rc4.tar.gz",
+ "has_sig":true,
+ "md5_digest":"1e0dc70edc40ff7bff6f8f7c6cd3fbbc",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size":1350101,
+ "upload_time":"2018-05-22T06:25:37",
+ "upload_time_iso_8601":"2018-05-22T06:25:37.461953Z",
+ "url":"https://files.pythonhosted.org/packages/b5/f7/f862b92e6fc7c3628712d69d8f5d41173db5bda27f0504b17444a79b98bc/celery-4.2.0rc4.tar.gz"
+ }
+ ],
+ "4.2.1":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"f48d95dc2fb83be1342ae8497120a63f",
+ "sha256":"ad7a7411772b80a4d6c64f2f7f723200e39fb66cf614a7fdfab76d345acc7b13"
+ },
+ "downloads":-1,
+ "filename":"celery-4.2.1-py2.py3-none-any.whl",
+ "has_sig":true,
+ "md5_digest":"f48d95dc2fb83be1342ae8497120a63f",
+ "packagetype":"bdist_wheel",
+ "python_version":"py2.py3",
+ "requires_python":">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size":401504,
+ "upload_time":"2018-07-18T08:17:01",
+ "upload_time_iso_8601":"2018-07-18T08:17:01.168316Z",
+ "url":"https://files.pythonhosted.org/packages/e8/58/2a0b1067ab2c12131b5c089dfc579467c76402475c5231095e36a43b749c/celery-4.2.1-py2.py3-none-any.whl"
+ },
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"71397f019700edc97a41ebadf09daf42",
+ "sha256":"77dab4677e24dc654d42dfbdfed65fa760455b6bb563a0877ecc35f4cfcfc678"
+ },
+ "downloads":-1,
+ "filename":"celery-4.2.1.tar.gz",
+ "has_sig":true,
+ "md5_digest":"71397f019700edc97a41ebadf09daf42",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size":1364075,
+ "upload_time":"2018-07-18T08:17:24",
+ "upload_time_iso_8601":"2018-07-18T08:17:24.648573Z",
+ "url":"https://files.pythonhosted.org/packages/1e/6e/b30be7e43bab0311a695dd2576b3bf4528af4fd7c98f382e1b4029d5fc6a/celery-4.2.1.tar.gz"
+ }
+ ],
+ "4.2.2":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"5e4095904097dbd19f28aaf564220b38",
+ "sha256":"373d6544c8d6ee66b9c1c9ba61ec4c74334c9a861306002662252bd5fd0ff6a1"
+ },
+ "downloads":-1,
+ "filename":"celery-4.2.2-py2.py3-none-any.whl",
+ "has_sig":true,
+ "md5_digest":"5e4095904097dbd19f28aaf564220b38",
+ "packagetype":"bdist_wheel",
+ "python_version":"py2.py3",
+ "requires_python":">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size":401395,
+ "upload_time":"2019-03-20T13:50:22",
+ "upload_time_iso_8601":"2019-03-20T13:50:22.098859Z",
+ "url":"https://files.pythonhosted.org/packages/24/e9/9741a5a8b83253e27293e77bd4319c84306019dfbfa4cc43fa250243c12f/celery-4.2.2-py2.py3-none-any.whl"
+ },
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"fd58baa026733777c0644b84710f5026",
+ "sha256":"b1b7da98be6b4082abfa6e18282ece450271f366bce81d0d521342a0db862506"
+ },
+ "downloads":-1,
+ "filename":"celery-4.2.2.tar.gz",
+ "has_sig":true,
+ "md5_digest":"fd58baa026733777c0644b84710f5026",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size":1356962,
+ "upload_time":"2019-03-20T13:50:30",
+ "upload_time_iso_8601":"2019-03-20T13:50:30.378776Z",
+ "url":"https://files.pythonhosted.org/packages/1b/45/080ca4860d32905fa0acffbb07b6a808382369bb2e53398060f1ffb02ef8/celery-4.2.2.tar.gz"
+ }
+ ],
+ "4.3.0":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"f1a0221fdd2666837bd6b879f577e715",
+ "sha256":"528e56767ae7e43a16cfef24ee1062491f5754368d38fcfffa861cdb9ef219be"
+ },
+ "downloads":-1,
+ "filename":"celery-4.3.0-py2.py3-none-any.whl",
+ "has_sig":true,
+ "md5_digest":"f1a0221fdd2666837bd6b879f577e715",
+ "packagetype":"bdist_wheel",
+ "python_version":"py2.py3",
+ "requires_python":">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size":413645,
+ "upload_time":"2019-03-31T15:56:34",
+ "upload_time_iso_8601":"2019-03-31T15:56:34.897053Z",
+ "url":"https://files.pythonhosted.org/packages/5c/a1/a3dd9d8bfa09156ec2cba37f90accf35c0f4ecc3980d96cb4fb99e56504b/celery-4.3.0-py2.py3-none-any.whl"
+ },
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"7015c93e6869276deedfd8638ca4a770",
+ "sha256":"4c4532aa683f170f40bd76f928b70bc06ff171a959e06e71bf35f2f9d6031ef9"
+ },
+ "downloads":-1,
+ "filename":"celery-4.3.0.tar.gz",
+ "has_sig":true,
+ "md5_digest":"7015c93e6869276deedfd8638ca4a770",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size":1398430,
+ "upload_time":"2019-03-31T15:56:39",
+ "upload_time_iso_8601":"2019-03-31T15:56:39.270570Z",
+ "url":"https://files.pythonhosted.org/packages/a2/4b/d020836f751617e907e84753a41c92231cd4b673ff991b8ee9da52361323/celery-4.3.0.tar.gz"
+ }
+ ],
+ "4.3.0rc1":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"d9456f438fa08dbdec7027aa90901162",
+ "sha256":"62cdf98af78278202b8a3ba1b8215c87ab420eae7eebf0b7ba27b16ebc9f148e"
+ },
+ "downloads":-1,
+ "filename":"celery-4.3.0rc1-py2.py3-none-any.whl",
+ "has_sig":true,
+ "md5_digest":"d9456f438fa08dbdec7027aa90901162",
+ "packagetype":"bdist_wheel",
+ "python_version":"py2.py3",
+ "requires_python":">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size":410279,
+ "upload_time":"2019-02-20T15:07:45",
+ "upload_time_iso_8601":"2019-02-20T15:07:45.547729Z",
+ "url":"https://files.pythonhosted.org/packages/55/64/4930488574a9b65e717315837172e9e7ea472107a9ebe8a1423910413e1e/celery-4.3.0rc1-py2.py3-none-any.whl"
+ },
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"2da74cd735d4c24eea1fd859a25a7bd2",
+ "sha256":"ce1f8068f8330e9552def4161f34ee667a1e3f5f8874425ee5768d05e821afca"
+ },
+ "downloads":-1,
+ "filename":"celery-4.3.0rc1.tar.gz",
+ "has_sig":true,
+ "md5_digest":"2da74cd735d4c24eea1fd859a25a7bd2",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size":1386540,
+ "upload_time":"2019-02-20T15:07:53",
+ "upload_time_iso_8601":"2019-02-20T15:07:53.385385Z",
+ "url":"https://files.pythonhosted.org/packages/b4/a0/d3c8dc6e4f9e5b04c0153ec8fd5613b4c864d8def446e4d97964022d467e/celery-4.3.0rc1.tar.gz"
+ }
+ ],
+ "4.3.0rc2":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"22a173dbd8c61bc5fced14ad06f48067",
+ "sha256":"44129fe6146a7ba96466d42e650f0444497fd9be542f8a9092716d2970804770"
+ },
+ "downloads":-1,
+ "filename":"celery-4.3.0rc2-py2.py3-none-any.whl",
+ "has_sig":true,
+ "md5_digest":"22a173dbd8c61bc5fced14ad06f48067",
+ "packagetype":"bdist_wheel",
+ "python_version":"py2.py3",
+ "requires_python":">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size":412403,
+ "upload_time":"2019-03-03T19:45:03",
+ "upload_time_iso_8601":"2019-03-03T19:45:03.765845Z",
+ "url":"https://files.pythonhosted.org/packages/2e/f7/50145a5ef22668535e2208b686d730d7423cc4cee7d7042dc4cfa57b6dca/celery-4.3.0rc2-py2.py3-none-any.whl"
+ },
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"bf52be3c1721bdd659f83f8c99899416",
+ "sha256":"fe05a3e2873d11990fe7c08319e8ca5bd2d0424b521f40f3d29b891134e5df00"
+ },
+ "downloads":-1,
+ "filename":"celery-4.3.0rc2.tar.gz",
+ "has_sig":true,
+ "md5_digest":"bf52be3c1721bdd659f83f8c99899416",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size":1390175,
+ "upload_time":"2019-03-03T19:45:23",
+ "upload_time_iso_8601":"2019-03-03T19:45:23.318033Z",
+ "url":"https://files.pythonhosted.org/packages/5a/01/3dbd8f110bc3f8cbb614612c36cc6c34b0177531d5f36413bbaf8c5d3009/celery-4.3.0rc2.tar.gz"
+ }
+ ],
+ "4.3.0rc3":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"bf16cb18d93f6023bef9d1b8878831c0",
+ "sha256":"a394953a4574619efc6bd84015a01649cf12c8123b6003132cad07f36b79aca5"
+ },
+ "downloads":-1,
+ "filename":"celery-4.3.0rc3-py2.py3-none-any.whl",
+ "has_sig":true,
+ "md5_digest":"bf16cb18d93f6023bef9d1b8878831c0",
+ "packagetype":"bdist_wheel",
+ "python_version":"py2.py3",
+ "requires_python":">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size":413167,
+ "upload_time":"2019-03-21T14:17:35",
+ "upload_time_iso_8601":"2019-03-21T14:17:35.307557Z",
+ "url":"https://files.pythonhosted.org/packages/73/e0/fd3714b5892311f1f802201ab287f47db10afdd7361b516a920fced18201/celery-4.3.0rc3-py2.py3-none-any.whl"
+ },
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"485ea6169e04a502ade70456f2cd04be",
+ "sha256":"8dcfaf39ba25a6830e4e029765a8872489eca7f0162d9bd12962c59da7bf5c9d"
+ },
+ "downloads":-1,
+ "filename":"celery-4.3.0rc3.tar.gz",
+ "has_sig":true,
+ "md5_digest":"485ea6169e04a502ade70456f2cd04be",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size":1395547,
+ "upload_time":"2019-03-21T14:17:53",
+ "upload_time_iso_8601":"2019-03-21T14:17:53.979627Z",
+ "url":"https://files.pythonhosted.org/packages/6f/58/6db69cf4a5de75c69732499de8ef1ea337771152fd5904fbb3594a896781/celery-4.3.0rc3.tar.gz"
+ }
+ ],
+ "4.4.0":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"f2d41b6be7bb0c26131bf55eac63fa0a",
+ "sha256":"7c544f37a84a5eadc44cab1aa8c9580dff94636bb81978cdf9bf8012d9ea7d8f"
+ },
+ "downloads":-1,
+ "filename":"celery-4.4.0-py2.py3-none-any.whl",
+ "has_sig":false,
+ "md5_digest":"f2d41b6be7bb0c26131bf55eac63fa0a",
+ "packagetype":"bdist_wheel",
+ "python_version":"py2.py3",
+ "requires_python":">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*,",
+ "size":421999,
+ "upload_time":"2019-12-16T03:47:33",
+ "upload_time_iso_8601":"2019-12-16T03:47:33.557633Z",
+ "url":"https://files.pythonhosted.org/packages/47/53/6e2ccc87b18ddc582d2de31b3ed9144c72a68062659e9e4a68e19312d254/celery-4.4.0-py2.py3-none-any.whl"
+ },
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"9c5d17291bf204662ecc972eec26789e",
+ "sha256":"d3363bb5df72d74420986a435449f3c3979285941dff57d5d97ecba352a0e3e2"
+ },
+ "downloads":-1,
+ "filename":"celery-4.4.0.tar.gz",
+ "has_sig":false,
+ "md5_digest":"9c5d17291bf204662ecc972eec26789e",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*,",
+ "size":1415339,
+ "upload_time":"2019-12-16T03:47:52",
+ "upload_time_iso_8601":"2019-12-16T03:47:52.661342Z",
+ "url":"https://files.pythonhosted.org/packages/b5/50/929ce161882c2f35a91aac02f1c6e8556bbdc2a8b53320fc44fa0b9a0cd4/celery-4.4.0.tar.gz"
+ }
+ ],
+ "4.4.0rc1":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"d12a9c682a93541224ca7329b486438c",
+ "sha256":"bc474e5dd9e2675e0a377aa577dd5efc9fc9e8b3932c9ab9809c53bab04b79b1"
+ },
+ "downloads":-1,
+ "filename":"celery-4.4.0rc1-py2.py3-none-any.whl",
+ "has_sig":false,
+ "md5_digest":"d12a9c682a93541224ca7329b486438c",
+ "packagetype":"bdist_wheel",
+ "python_version":"py2.py3",
+ "requires_python":">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*,",
+ "size":415594,
+ "upload_time":"2019-06-06T07:10:04",
+ "upload_time_iso_8601":"2019-06-06T07:10:04.678783Z",
+ "url":"https://files.pythonhosted.org/packages/55/fb/ed96664165c3e459e71cc04acc68f1cbd1fcb6ee1c712b0ff51c5f2b9491/celery-4.4.0rc1-py2.py3-none-any.whl"
+ },
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"f5cf4f530dac79af5ac3b6ff6c29494c",
+ "sha256":"a43d00f85f949ea0fb046fdc3c20d56d30d9e21bc77844be29a8f29db3539db3"
+ },
+ "downloads":-1,
+ "filename":"celery-4.4.0rc1.tar.gz",
+ "has_sig":false,
+ "md5_digest":"f5cf4f530dac79af5ac3b6ff6c29494c",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*,",
+ "size":1403063,
+ "upload_time":"2019-06-06T07:10:11",
+ "upload_time_iso_8601":"2019-06-06T07:10:11.778122Z",
+ "url":"https://files.pythonhosted.org/packages/e8/af/8802e51e362e7126f3962d26d2611c35d5474bb718762671e32b0b897fe8/celery-4.4.0rc1.tar.gz"
+ }
+ ],
+ "4.4.0rc2":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"0fadf579e535317b5c56f3978aef7e7f",
+ "sha256":"42d77e2ad99b8cf3950ca8b872f7310fc9dfbeb3ba68ec10a25cd63c87043db1"
+ },
+ "downloads":-1,
+ "filename":"celery-4.4.0rc2-py2.py3-none-any.whl",
+ "has_sig":false,
+ "md5_digest":"0fadf579e535317b5c56f3978aef7e7f",
+ "packagetype":"bdist_wheel",
+ "python_version":"py2.py3",
+ "requires_python":">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*,",
+ "size":415758,
+ "upload_time":"2019-06-14T22:25:10",
+ "upload_time_iso_8601":"2019-06-14T22:25:10.321096Z",
+ "url":"https://files.pythonhosted.org/packages/bf/33/37694cf1ecd8f5a8e3f538e73db9d4c38f308ae51295fd4f6d0281a31bcb/celery-4.4.0rc2-py2.py3-none-any.whl"
+ },
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"982d708b676191b87fca449f95d1a856",
+ "sha256":"8f7f479b1cbfd5e10c184d744801695e7187901a0c99bedd50ae9b6a8cf351d1"
+ },
+ "downloads":-1,
+ "filename":"celery-4.4.0rc2.tar.gz",
+ "has_sig":false,
+ "md5_digest":"982d708b676191b87fca449f95d1a856",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*,",
+ "size":1405214,
+ "upload_time":"2019-06-14T22:25:24",
+ "upload_time_iso_8601":"2019-06-14T22:25:24.310608Z",
+ "url":"https://files.pythonhosted.org/packages/71/3b/90beebd960427fd019fc35e77b88a218db8050731871a2995bf8d3138634/celery-4.4.0rc2.tar.gz"
+ }
+ ],
+ "4.4.0rc3":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"a19809e45cfdb2403f532c76ea3d9859",
+ "sha256":"821d11967f0f3f8fe24bd61ecfc7b6acbb5a926b719f1e8c4d5ff7bc09e18d81"
+ },
+ "downloads":-1,
+ "filename":"celery-4.4.0rc3-py2.py3-none-any.whl",
+ "has_sig":false,
+ "md5_digest":"a19809e45cfdb2403f532c76ea3d9859",
+ "packagetype":"bdist_wheel",
+ "python_version":"py2.py3",
+ "requires_python":">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*,",
+ "size":417126,
+ "upload_time":"2019-08-14T17:05:04",
+ "upload_time_iso_8601":"2019-08-14T17:05:04.970304Z",
+ "url":"https://files.pythonhosted.org/packages/dd/70/173e8f817ec7623fa756c3afbd0e1ee784836028e5aa180ea558b09af712/celery-4.4.0rc3-py2.py3-none-any.whl"
+ },
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"777b00059ed9711801b991c68b32f823",
+ "sha256":"ae4541fb3af5182bd4af749fee9b89c4858f2792d34bb5d034967e662cf9b55c"
+ },
+ "downloads":-1,
+ "filename":"celery-4.4.0rc3.tar.gz",
+ "has_sig":false,
+ "md5_digest":"777b00059ed9711801b991c68b32f823",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*,",
+ "size":1408274,
+ "upload_time":"2019-08-14T17:05:13",
+ "upload_time_iso_8601":"2019-08-14T17:05:13.988362Z",
+ "url":"https://files.pythonhosted.org/packages/38/b7/b5e563d1967bf079cfa63f8df3e7a004e81b663e42d034228654cf835200/celery-4.4.0rc3.tar.gz"
+ }
+ ],
+ "4.4.0rc4":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"821b9519771b893eec0edd66d61b1b2e",
+ "sha256":"65f4d67fc1037edacecbf39fcf956da68b984cf2a6d89bd73a8a5a80e35e3dd7"
+ },
+ "downloads":-1,
+ "filename":"celery-4.4.0rc4-py2.py3-none-any.whl",
+ "has_sig":false,
+ "md5_digest":"821b9519771b893eec0edd66d61b1b2e",
+ "packagetype":"bdist_wheel",
+ "python_version":"py2.py3",
+ "requires_python":">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*,",
+ "size":419091,
+ "upload_time":"2019-11-10T18:51:25",
+ "upload_time_iso_8601":"2019-11-10T18:51:25.033234Z",
+ "url":"https://files.pythonhosted.org/packages/90/2d/d184fcb0fd85fd43ebca8a36e2d8a7080a1d5532c5dc0c21fdb73873f9d3/celery-4.4.0rc4-py2.py3-none-any.whl"
+ },
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"de9d5822589080dcbe2dab521afd136a",
+ "sha256":"8a59d80235b876881d9893751f2a87936165fc1347efee66095620b3cadf533b"
+ },
+ "downloads":-1,
+ "filename":"celery-4.4.0rc4.tar.gz",
+ "has_sig":false,
+ "md5_digest":"de9d5822589080dcbe2dab521afd136a",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*,",
+ "size":1413803,
+ "upload_time":"2019-11-10T18:51:38",
+ "upload_time_iso_8601":"2019-11-10T18:51:38.511696Z",
+ "url":"https://files.pythonhosted.org/packages/3c/7b/3c7fa56ed29e6f27a8a14c6cf21b6a8af641cff3097adc7b138bbabe96a6/celery-4.4.0rc4.tar.gz"
+ }
+ ],
+ "4.4.0rc5":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"b24bfad910065e44a27a157ba2ef38a8",
+ "sha256":"395599ad0728eeee4cb899c99568e5a8a885f54aee377c31b626b24bf3b35cd0"
+ },
+ "downloads":-1,
+ "filename":"celery-4.4.0rc5-py2.py3-none-any.whl",
+ "has_sig":false,
+ "md5_digest":"b24bfad910065e44a27a157ba2ef38a8",
+ "packagetype":"bdist_wheel",
+ "python_version":"py2.py3",
+ "requires_python":">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*,",
+ "size":421982,
+ "upload_time":"2019-12-07T15:07:19",
+ "upload_time_iso_8601":"2019-12-07T15:07:19.596419Z",
+ "url":"https://files.pythonhosted.org/packages/9e/81/ed54e8c9b7892f3700caa7c1e116925a4066061a2b576945d41e77267857/celery-4.4.0rc5-py2.py3-none-any.whl"
+ },
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"3cd1289b2905b22d995f3b373df44fe8",
+ "sha256":"2fa97a53855014148f7d41455e3e0869ab45fb6f777df6c6b1701f03c55c573a"
+ },
+ "downloads":-1,
+ "filename":"celery-4.4.0rc5.tar.gz",
+ "has_sig":false,
+ "md5_digest":"3cd1289b2905b22d995f3b373df44fe8",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*,",
+ "size":1412452,
+ "upload_time":"2019-12-07T15:07:38",
+ "upload_time_iso_8601":"2019-12-07T15:07:38.591951Z",
+ "url":"https://files.pythonhosted.org/packages/99/72/127bd339548455b31ff5a7c744ef960479c0303c3b59fc5a5688a4ad9385/celery-4.4.0rc5.tar.gz"
+ }
+ ]
+ },
+ "urls":[
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"f2d41b6be7bb0c26131bf55eac63fa0a",
+ "sha256":"7c544f37a84a5eadc44cab1aa8c9580dff94636bb81978cdf9bf8012d9ea7d8f"
+ },
+ "downloads":-1,
+ "filename":"celery-4.4.0-py2.py3-none-any.whl",
+ "has_sig":false,
+ "md5_digest":"f2d41b6be7bb0c26131bf55eac63fa0a",
+ "packagetype":"bdist_wheel",
+ "python_version":"py2.py3",
+ "requires_python":">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*,",
+ "size":421999,
+ "upload_time":"2019-12-16T03:47:33",
+ "upload_time_iso_8601":"2019-12-16T03:47:33.557633Z",
+ "url":"https://files.pythonhosted.org/packages/47/53/6e2ccc87b18ddc582d2de31b3ed9144c72a68062659e9e4a68e19312d254/celery-4.4.0-py2.py3-none-any.whl"
+ },
+ {
+ "comment_text":"",
+ "digests":{
+ "md5":"9c5d17291bf204662ecc972eec26789e",
+ "sha256":"d3363bb5df72d74420986a435449f3c3979285941dff57d5d97ecba352a0e3e2"
+ },
+ "downloads":-1,
+ "filename":"celery-4.4.0.tar.gz",
+ "has_sig":false,
+ "md5_digest":"9c5d17291bf204662ecc972eec26789e",
+ "packagetype":"sdist",
+ "python_version":"source",
+ "requires_python":">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*,",
+ "size":1415339,
+ "upload_time":"2019-12-16T03:47:52",
+ "upload_time_iso_8601":"2019-12-16T03:47:52.661342Z",
+ "url":"https://files.pythonhosted.org/packages/b5/50/929ce161882c2f35a91aac02f1c6e8556bbdc2a8b53320fc44fa0b9a0cd4/celery-4.4.0.tar.gz"
+ }
+ ]
+}
diff --git a/uv/spec/fixtures/pypi/pypi_response_no_source.json b/uv/spec/fixtures/pypi/pypi_response_no_source.json
new file mode 100644
index 00000000000..7fcb82256a8
--- /dev/null
+++ b/uv/spec/fixtures/pypi/pypi_response_no_source.json
@@ -0,0 +1,979 @@
+{
+ "info": {
+ "maintainer": null,
+ "docs_url": "http://pythonhosted.org/psycopg2/",
+ "requires_python": null,
+ "maintainer_email": null,
+ "cheesecake_code_kwalitee_id": null,
+ "keywords": null,
+ "package_url": "http://pypi.org/pypi/psycopg2",
+ "author": "Federico Di Gregorio",
+ "author_email": "fog@initd.org",
+ "download_url": "http://initd.org/psycopg/tarballs/PSYCOPG-2-6/psycopg2-2.6.2.tar.gz",
+ "platform": "any",
+ "version": "2.6.2",
+ "cheesecake_documentation_id": null,
+ "_pypi_hidden": false,
+ "description": "Psycopg is the most popular PostgreSQL database adapter for the Python\nprogramming language. Its main features are the complete implementation of\nthe Python DB API 2.0 specification and the thread safety (several threads can\nshare the same connection). It was designed for heavily multi-threaded\napplications that create and destroy lots of cursors and make a large number\nof concurrent \"INSERT\"s or \"UPDATE\"s.\n\nPsycopg 2 is mostly implemented in C as a libpq wrapper, resulting in being\nboth efficient and secure. It features client-side and server-side cursors,\nasynchronous communication and notifications, \"COPY TO/COPY FROM\" support.\nMany Python types are supported out-of-the-box and adapted to matching\nPostgreSQL data types; adaptation can be extended and customized thanks to a\nflexible objects adaptation system.\n\nPsycopg 2 is both Unicode and Python 3 friendly.\n\n\nDocumentation\n-------------\n\nDocumentation is included in the 'doc' directory and is `available online`__.\n\n.. __: http://initd.org/psycopg/docs/\n\n\nInstallation\n------------\n\nIf all the dependencies are met (i.e. you have the Python and libpq\ndevelopment packages installed in your system) the standard::\n\n python setup.py build\n sudo python setup.py install\n\nshould work no problem. In case you have any problem check the 'install' and\nthe 'faq' documents in the docs or online__.\n\n.. __: http://initd.org/psycopg/docs/install.html\n\nFor any other resource (source code repository, bug tracker, mailing list)\nplease check the `project homepage`__.\n\n.. __: http://initd.org/psycopg/",
+ "release_url": "http://pypi.org/pypi/psycopg2/2.6.2",
+ "downloads": {
+ "last_month": 0,
+ "last_week": 0,
+ "last_day": 0
+ },
+ "_pypi_ordering": 33,
+ "classifiers": [
+ "Development Status :: 5 - Production/Stable",
+ "Intended Audience :: Developers",
+ "License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL)",
+ "License :: OSI Approved :: Zope Public License",
+ "Operating System :: Microsoft :: Windows",
+ "Operating System :: Unix",
+ "Programming Language :: C",
+ "Programming Language :: Python",
+ "Programming Language :: Python :: 2.5",
+ "Programming Language :: Python :: 2.6",
+ "Programming Language :: Python :: 2.7",
+ "Programming Language :: Python :: 3",
+ "Programming Language :: Python :: 3.1",
+ "Programming Language :: Python :: 3.2",
+ "Programming Language :: Python :: 3.3",
+ "Programming Language :: Python :: 3.4",
+ "Programming Language :: Python :: 3.5",
+ "Programming Language :: SQL",
+ "Topic :: Database",
+ "Topic :: Database :: Front-Ends",
+ "Topic :: Software Development",
+ "Topic :: Software Development :: Libraries :: Python Modules"
+ ],
+ "name": "psycopg2",
+ "bugtrack_url": null,
+ "license": "LGPL with exceptions or ZPL",
+ "summary": "psycopg2 - Python-PostgreSQL Database Adapter",
+ "home_page": "http://initd.org/psycopg/",
+ "cheesecake_installability_id": null
+ },
+ "releases": {
+ "2.0.7": [],
+ "2.0.6": [],
+ "2.0.4": [],
+ "2.0.3": [],
+ "2.0.2": [],
+ "2.0.5.1": [],
+ "2.0.8": [],
+ "2.6": [
+ {
+ "has_sig": true,
+ "upload_time": "2015-02-09T10:02:22",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/dd/c7/9016ff8ff69da269b1848276eebfb264af5badf6b38caad805426771f04d/psycopg2-2.6.tar.gz",
+ "md5_digest": "fbbb039a8765d561a1c04969bbae7c74",
+ "downloads": 1787225,
+ "filename": "psycopg2-2.6.tar.gz",
+ "packagetype": "sdist",
+ "path": "dd/c7/9016ff8ff69da269b1848276eebfb264af5badf6b38caad805426771f04d/psycopg2-2.6.tar.gz",
+ "size": 367972
+ }
+ ],
+ "2.2.1": [
+ {
+ "has_sig": false,
+ "upload_time": "2010-10-19T15:42:13",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/de/c4/fdfb801035bd7da9e1ce98169d48ca2d6dee5b4361e349afbba40b3d7a5d/psycopg2-2.2.1.tar.gz",
+ "md5_digest": "70b50773aefe5fb371ff4a018382012f",
+ "downloads": 44315,
+ "filename": "psycopg2-2.2.1.tar.gz",
+ "packagetype": "sdist",
+ "path": "de/c4/fdfb801035bd7da9e1ce98169d48ca2d6dee5b4361e349afbba40b3d7a5d/psycopg2-2.2.1.tar.gz",
+ "size": 529408
+ }
+ ],
+ "2.2.0": [
+ {
+ "has_sig": false,
+ "upload_time": "2010-10-19T15:41:50",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/32/0c/2f4da04ae2a66d71eff37f19fce67506ad28f887851cd1c1cca35ba08b36/psycopg2-2.2.0.tar.gz",
+ "md5_digest": "4a69436dc8efbfe2859ae3aeed85d03e",
+ "downloads": 5166,
+ "filename": "psycopg2-2.2.0.tar.gz",
+ "packagetype": "sdist",
+ "path": "32/0c/2f4da04ae2a66d71eff37f19fce67506ad28f887851cd1c1cca35ba08b36/psycopg2-2.2.0.tar.gz",
+ "size": 528718
+ }
+ ],
+ "2.2.2": [
+ {
+ "has_sig": false,
+ "upload_time": "2010-09-09T10:53:08",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/63/3e/a4a35761eb4595fff89e63347b4f8e79c2095782fa5bc016a6dfb18b21ac/psycopg2-2.2.2.tar.gz",
+ "md5_digest": "571af2ad9dfeb522ee5f8553278a4c38",
+ "downloads": 27853,
+ "filename": "psycopg2-2.2.2.tar.gz",
+ "packagetype": "sdist",
+ "path": "63/3e/a4a35761eb4595fff89e63347b4f8e79c2095782fa5bc016a6dfb18b21ac/psycopg2-2.2.2.tar.gz",
+ "size": 530021
+ }
+ ],
+ "2.5.4": [
+ {
+ "has_sig": true,
+ "upload_time": "2014-08-30T18:04:42",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/63/c3/802668cb3cfc2880c2a8364623e7105a0257724a2612bb66ec733aaddb8c/psycopg2-2.5.4.tar.gz",
+ "md5_digest": "25216543a707eb33fd83aa8efb6e3f26",
+ "downloads": 1866067,
+ "filename": "psycopg2-2.5.4.tar.gz",
+ "packagetype": "sdist",
+ "path": "63/c3/802668cb3cfc2880c2a8364623e7105a0257724a2612bb66ec733aaddb8c/psycopg2-2.5.4.tar.gz",
+ "size": 682578
+ }
+ ],
+ "2.5": [
+ {
+ "has_sig": true,
+ "upload_time": "2013-04-07T18:18:13",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/84/7e/7256298bf7064238e63b9380cf424f776a4d2a87e387c9a9bd1bc5ea0fbc/psycopg2-2.5.tar.gz",
+ "md5_digest": "facd82faa067e99b80146a0ee2f842f6",
+ "downloads": 239430,
+ "filename": "psycopg2-2.5.tar.gz",
+ "packagetype": "sdist",
+ "path": "84/7e/7256298bf7064238e63b9380cf424f776a4d2a87e387c9a9bd1bc5ea0fbc/psycopg2-2.5.tar.gz",
+ "size": 703558
+ }
+ ],
+ "2.4": [
+ {
+ "has_sig": false,
+ "upload_time": "2011-02-27T16:52:11",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/ce/2d/e9e65ee32ef2657028109bd5a1c1ece97e409ebf790b6ee286aae2c6b890/psycopg2-2.4.tar.gz",
+ "md5_digest": "24f4368e2cfdc1a2b03282ddda814160",
+ "downloads": 78219,
+ "filename": "psycopg2-2.4.tar.gz",
+ "packagetype": "sdist",
+ "path": "ce/2d/e9e65ee32ef2657028109bd5a1c1ece97e409ebf790b6ee286aae2c6b890/psycopg2-2.4.tar.gz",
+ "size": 607925
+ }
+ ],
+ "2.4.6": [
+ {
+ "has_sig": true,
+ "upload_time": "2012-12-12T10:51:33",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/59/aa/4d74a5dc32a89d622c1fa896a86683b488ef255f06d4b27231e12e6076f7/psycopg2-2.4.6.tar.gz",
+ "md5_digest": "79d7f05e67bf70a0ecc6e9103ccece5f",
+ "downloads": 464523,
+ "filename": "psycopg2-2.4.6.tar.gz",
+ "packagetype": "sdist",
+ "path": "59/aa/4d74a5dc32a89d622c1fa896a86683b488ef255f06d4b27231e12e6076f7/psycopg2-2.4.6.tar.gz",
+ "size": 667783
+ }
+ ],
+ "2.5.1": [
+ {
+ "has_sig": true,
+ "upload_time": "2013-06-23T19:24:08",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/22/09/63d5da7375c267e208bbadf56b51699d85cb7b3a9096817eeea500a27b3b/psycopg2-2.5.1.tar.gz",
+ "md5_digest": "1b433f83d50d1bc61e09026e906d84c7",
+ "downloads": 1488696,
+ "filename": "psycopg2-2.5.1.tar.gz",
+ "packagetype": "sdist",
+ "path": "22/09/63d5da7375c267e208bbadf56b51699d85cb7b3a9096817eeea500a27b3b/psycopg2-2.5.1.tar.gz",
+ "size": 684504
+ }
+ ],
+ "2.3.0": [
+ {
+ "has_sig": false,
+ "upload_time": "2010-12-02T00:53:24",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/68/0a/459df8dcbcc118ca435e9567abceaab919706908d52139e503f6396c4935/psycopg2-2.3.0.tar.gz",
+ "md5_digest": "0b52101b47f1e73001c6412d9a476222",
+ "downloads": 6552,
+ "filename": "psycopg2-2.3.0.tar.gz",
+ "packagetype": "sdist",
+ "path": "68/0a/459df8dcbcc118ca435e9567abceaab919706908d52139e503f6396c4935/psycopg2-2.3.0.tar.gz",
+ "size": 588979
+ }
+ ],
+ "2.3.1": [
+ {
+ "has_sig": false,
+ "upload_time": "2010-12-04T22:24:29",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/cd/7c/6acf5aacd347f3dc1398eca0e2123c35a48efb07617d4d9578e9cd79a1a7/psycopg2-2.3.1.tar.gz",
+ "md5_digest": "15d1c7f821f3a0306955d6cde3e762af",
+ "downloads": 20602,
+ "filename": "psycopg2-2.3.1.tar.gz",
+ "packagetype": "sdist",
+ "path": "cd/7c/6acf5aacd347f3dc1398eca0e2123c35a48efb07617d4d9578e9cd79a1a7/psycopg2-2.3.1.tar.gz",
+ "size": 567191
+ }
+ ],
+ "2.3.2": [
+ {
+ "has_sig": false,
+ "upload_time": "2011-02-18T12:33:34",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/50/48/32927cbc99633613704950be5013fc144aa0f451a5e0616635a934d94a62/psycopg2-2.3.2.tar.gz",
+ "md5_digest": "11e8021a4fda49faa15495f8bea65f4d",
+ "downloads": 11128,
+ "filename": "psycopg2-2.3.2.tar.gz",
+ "packagetype": "sdist",
+ "path": "50/48/32927cbc99633613704950be5013fc144aa0f451a5e0616635a934d94a62/psycopg2-2.3.2.tar.gz",
+ "size": 568029
+ }
+ ],
+ "2.4.3": [
+ {
+ "has_sig": false,
+ "upload_time": "2011-12-12T12:15:35",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/1e/71/8929172068cbc3d3c7288bf888a7df5862a28d67ed61ad9b4c7aa5cf8be8/psycopg2-2.4.3.tar.gz",
+ "md5_digest": "5f67ca0c8b6c1ac5c4afd82811e0facc",
+ "downloads": 16990,
+ "filename": "psycopg2-2.4.3.tar.gz",
+ "packagetype": "sdist",
+ "path": "1e/71/8929172068cbc3d3c7288bf888a7df5862a28d67ed61ad9b4c7aa5cf8be8/psycopg2-2.4.3.tar.gz",
+ "size": 647008
+ }
+ ],
+ "2.4.2": [
+ {
+ "has_sig": false,
+ "upload_time": "2011-06-17T15:15:38",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/70/91/345f8eb32dc333331510e1adad858f7a1478d3a1e4aae05ee188985c6b17/psycopg2-2.4.2.tar.gz",
+ "md5_digest": "58cfd294d28b7e8ef059d72085d71ac2",
+ "downloads": 105108,
+ "filename": "psycopg2-2.4.2.tar.gz",
+ "packagetype": "sdist",
+ "path": "70/91/345f8eb32dc333331510e1adad858f7a1478d3a1e4aae05ee188985c6b17/psycopg2-2.4.2.tar.gz",
+ "size": 667192
+ }
+ ],
+ "2.4.1": [
+ {
+ "has_sig": false,
+ "upload_time": "2011-05-11T12:56:53",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/82/f8/6c80beb1b58f01f52dcdfa52bc1668caa4e3fc4927e9230edc40afa98c05/psycopg2-2.4.1.tar.gz",
+ "md5_digest": "4e79c822ab75dd89d931ee627c66032f",
+ "downloads": 219576,
+ "filename": "psycopg2-2.4.1.tar.gz",
+ "packagetype": "sdist",
+ "path": "82/f8/6c80beb1b58f01f52dcdfa52bc1668caa4e3fc4927e9230edc40afa98c05/psycopg2-2.4.1.tar.gz",
+ "size": 398200
+ }
+ ],
+ "2.5.5": [
+ {
+ "has_sig": true,
+ "upload_time": "2015-02-09T09:59:31",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/9b/60/f4c79e73a69ded145880bcf4f98eeed741af12c62c5ddc89b754602b1807/psycopg2-2.5.5.tar.gz",
+ "md5_digest": "1404a6cc0108eed5d7dd0c1dc9a1c074",
+ "downloads": 64048,
+ "filename": "psycopg2-2.5.5.tar.gz",
+ "packagetype": "sdist",
+ "path": "9b/60/f4c79e73a69ded145880bcf4f98eeed741af12c62c5ddc89b754602b1807/psycopg2-2.5.5.tar.gz",
+ "size": 779757
+ }
+ ],
+ "2.5.2": [
+ {
+ "has_sig": true,
+ "upload_time": "2014-01-07T12:25:11",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/c3/f3/5519551f02ae70fc51f4e608e7b44d59a408fe3264fec4afeea37b8ea317/psycopg2-2.5.2.tar.gz",
+ "md5_digest": "53d81793fbab8fee6e732a0425d50047",
+ "downloads": 1030601,
+ "filename": "psycopg2-2.5.2.tar.gz",
+ "packagetype": "sdist",
+ "path": "c3/f3/5519551f02ae70fc51f4e608e7b44d59a408fe3264fec4afeea37b8ea317/psycopg2-2.5.2.tar.gz",
+ "size": 685762
+ }
+ ],
+ "2.5.3": [
+ {
+ "has_sig": true,
+ "upload_time": "2014-05-13T16:51:38",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/22/fa/5ddcafc7387c1534c59eb3ffcdb9ab2af106fd3b104e6df191b6c55718af/psycopg2-2.5.3.tar.gz",
+ "md5_digest": "09dcec70f623a9ef774f1aef75690995",
+ "downloads": 1114861,
+ "filename": "psycopg2-2.5.3.tar.gz",
+ "packagetype": "sdist",
+ "path": "22/fa/5ddcafc7387c1534c59eb3ffcdb9ab2af106fd3b104e6df191b6c55718af/psycopg2-2.5.3.tar.gz",
+ "size": 690689
+ }
+ ],
+ "2.4.5": [
+ {
+ "has_sig": true,
+ "upload_time": "2012-03-29T11:42:27",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/36/77/894a5dd9f3f55cfc85682d3e6473ee5103d8d418b95baf4019fad3ffa026/psycopg2-2.4.5.tar.gz",
+ "md5_digest": "075e4df465e9a863f288d5bdf6e6887e",
+ "downloads": 7212996,
+ "filename": "psycopg2-2.4.5.tar.gz",
+ "packagetype": "sdist",
+ "path": "36/77/894a5dd9f3f55cfc85682d3e6473ee5103d8d418b95baf4019fad3ffa026/psycopg2-2.4.5.tar.gz",
+ "size": 719343
+ }
+ ],
+ "2.4.4": [
+ {
+ "has_sig": false,
+ "upload_time": "2011-12-19T13:38:39",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/6f/91/890c6f954e2d09d26b266a24468570c6227de61ac6f64926c48000db0a6e/psycopg2-2.4.4.tar.gz",
+ "md5_digest": "639e014ea9ce3aa3306724f12d16d79b",
+ "downloads": 102479,
+ "filename": "psycopg2-2.4.4.tar.gz",
+ "packagetype": "sdist",
+ "path": "6f/91/890c6f954e2d09d26b266a24468570c6227de61ac6f64926c48000db0a6e/psycopg2-2.4.4.tar.gz",
+ "size": 648954
+ }
+ ],
+ "2.6.1": [
+ {
+ "has_sig": false,
+ "upload_time": "2015-11-06T21:07:04",
+ "comment_text": "",
+ "python_version": "cp26",
+ "url": "https://pypi.org/packages/47/ed/5bd02bf1a7f78823f8a708beb3656f7c3ad935fb013c7063ff5f67848a52/psycopg2-2.6.1-cp26-none-win32.whl",
+ "md5_digest": "a849b57608acf6ae26db67cf6b7667b5",
+ "downloads": 1109,
+ "filename": "psycopg2-2.6.1-cp26-none-win32.whl",
+ "packagetype": "bdist_wheel",
+ "path": "47/ed/5bd02bf1a7f78823f8a708beb3656f7c3ad935fb013c7063ff5f67848a52/psycopg2-2.6.1-cp26-none-win32.whl",
+ "size": 814523
+ },
+ {
+ "has_sig": false,
+ "upload_time": "2015-11-06T21:07:14",
+ "comment_text": "",
+ "python_version": "cp26",
+ "url": "https://pypi.org/packages/2e/40/8ab9a8d99b7abd2b95858872fee6894a3eb4fc361692abc02e94091aa54b/psycopg2-2.6.1-cp26-none-win_amd64.whl",
+ "md5_digest": "66fda625af6267f020abc06a66afe75b",
+ "downloads": 921,
+ "filename": "psycopg2-2.6.1-cp26-none-win_amd64.whl",
+ "packagetype": "bdist_wheel",
+ "path": "2e/40/8ab9a8d99b7abd2b95858872fee6894a3eb4fc361692abc02e94091aa54b/psycopg2-2.6.1-cp26-none-win_amd64.whl",
+ "size": 1162332
+ },
+ {
+ "has_sig": false,
+ "upload_time": "2015-11-06T21:07:21",
+ "comment_text": "",
+ "python_version": "cp27",
+ "url": "https://pypi.org/packages/1f/84/a2fffb87348bc688d70bcdc24e761b06f48d958e1c1adfc3fa9eb3f4379c/psycopg2-2.6.1-cp27-none-win32.whl",
+ "md5_digest": "089acf7f1a8349c6308106bec896c762",
+ "downloads": 13199,
+ "filename": "psycopg2-2.6.1-cp27-none-win32.whl",
+ "packagetype": "bdist_wheel",
+ "path": "1f/84/a2fffb87348bc688d70bcdc24e761b06f48d958e1c1adfc3fa9eb3f4379c/psycopg2-2.6.1-cp27-none-win32.whl",
+ "size": 814322
+ },
+ {
+ "has_sig": false,
+ "upload_time": "2015-11-06T21:07:28",
+ "comment_text": "",
+ "python_version": "cp27",
+ "url": "https://pypi.org/packages/b5/37/b6e759f1f6a0fd32ad0e1b2576bf94cfa252710cad66e155f47fc04ba744/psycopg2-2.6.1-cp27-none-win_amd64.whl",
+ "md5_digest": "a8d7808e7c67e5bc0b6088a56045d2d2",
+ "downloads": 5864,
+ "filename": "psycopg2-2.6.1-cp27-none-win_amd64.whl",
+ "packagetype": "bdist_wheel",
+ "path": "b5/37/b6e759f1f6a0fd32ad0e1b2576bf94cfa252710cad66e155f47fc04ba744/psycopg2-2.6.1-cp27-none-win_amd64.whl",
+ "size": 1162753
+ },
+ {
+ "has_sig": false,
+ "upload_time": "2015-11-06T21:07:36",
+ "comment_text": "",
+ "python_version": "cp32",
+ "url": "https://pypi.org/packages/20/84/aaaf44c339a3b51196b8b1d0928899cbc02e1583ec455b6777011fdb63b0/psycopg2-2.6.1-cp32-none-win32.whl",
+ "md5_digest": "c8a704a73f0ea6369ea74a5a24e8f8db",
+ "downloads": 610,
+ "filename": "psycopg2-2.6.1-cp32-none-win32.whl",
+ "packagetype": "bdist_wheel",
+ "path": "20/84/aaaf44c339a3b51196b8b1d0928899cbc02e1583ec455b6777011fdb63b0/psycopg2-2.6.1-cp32-none-win32.whl",
+ "size": 815145
+ },
+ {
+ "has_sig": false,
+ "upload_time": "2015-11-06T21:07:44",
+ "comment_text": "",
+ "python_version": "cp32",
+ "url": "https://pypi.org/packages/84/50/ff71daf3e32a8bff56ac661eff9226d035abaf45fe1af007cfb2134970b3/psycopg2-2.6.1-cp32-none-win_amd64.whl",
+ "md5_digest": "e29046e7095483ecacac9e3390318254",
+ "downloads": 620,
+ "filename": "psycopg2-2.6.1-cp32-none-win_amd64.whl",
+ "packagetype": "bdist_wheel",
+ "path": "84/50/ff71daf3e32a8bff56ac661eff9226d035abaf45fe1af007cfb2134970b3/psycopg2-2.6.1-cp32-none-win_amd64.whl",
+ "size": 1163315
+ },
+ {
+ "has_sig": false,
+ "upload_time": "2015-11-06T19:48:39",
+ "comment_text": "",
+ "python_version": "cp33",
+ "url": "https://pypi.org/packages/2c/5a/8334a55459289cf8d7485a42bcb2dbe0dab5162973ef66a96baee5107593/psycopg2-2.6.1-cp33-none-win32.whl",
+ "md5_digest": "f438d2c01fbaa8f9d0cb150154448a9f",
+ "downloads": 769,
+ "filename": "psycopg2-2.6.1-cp33-none-win32.whl",
+ "packagetype": "bdist_wheel",
+ "path": "2c/5a/8334a55459289cf8d7485a42bcb2dbe0dab5162973ef66a96baee5107593/psycopg2-2.6.1-cp33-none-win32.whl",
+ "size": 818485
+ },
+ {
+ "has_sig": false,
+ "upload_time": "2015-11-06T19:48:52",
+ "comment_text": "",
+ "python_version": "cp33",
+ "url": "https://pypi.org/packages/7b/ed/82f31122dcc502d8f43c208a74eaa2b9ff39421aaab1ff8d61547639a474/psycopg2-2.6.1-cp33-none-win_amd64.whl",
+ "md5_digest": "632ab3d538a8239b619d434c5e17baf5",
+ "downloads": 875,
+ "filename": "psycopg2-2.6.1-cp33-none-win_amd64.whl",
+ "packagetype": "bdist_wheel",
+ "path": "7b/ed/82f31122dcc502d8f43c208a74eaa2b9ff39421aaab1ff8d61547639a474/psycopg2-2.6.1-cp33-none-win_amd64.whl",
+ "size": 1160268
+ },
+ {
+ "has_sig": false,
+ "upload_time": "2015-11-06T19:49:07",
+ "comment_text": "",
+ "python_version": "cp34",
+ "url": "https://pypi.org/packages/f0/34/894f8f486196fdb15d376f77a0102b25628ec0ac71538ed019b3ea93b907/psycopg2-2.6.1-cp34-none-win32.whl",
+ "md5_digest": "9d90c554f68cfabed7fdb90107e9d464",
+ "downloads": 2628,
+ "filename": "psycopg2-2.6.1-cp34-none-win32.whl",
+ "packagetype": "bdist_wheel",
+ "path": "f0/34/894f8f486196fdb15d376f77a0102b25628ec0ac71538ed019b3ea93b907/psycopg2-2.6.1-cp34-none-win32.whl",
+ "size": 818452
+ },
+ {
+ "has_sig": false,
+ "upload_time": "2015-11-06T19:49:19",
+ "comment_text": "",
+ "python_version": "cp34",
+ "url": "https://pypi.org/packages/b7/90/23af1a90f06dfa012a4ae829821b3161344a9e447358841779d027f14bd7/psycopg2-2.6.1-cp34-none-win_amd64.whl",
+ "md5_digest": "4c95328c20e00efc66f0046823f6d1d0",
+ "downloads": 3142,
+ "filename": "psycopg2-2.6.1-cp34-none-win_amd64.whl",
+ "packagetype": "bdist_wheel",
+ "path": "b7/90/23af1a90f06dfa012a4ae829821b3161344a9e447358841779d027f14bd7/psycopg2-2.6.1-cp34-none-win_amd64.whl",
+ "size": 1160261
+ },
+ {
+ "has_sig": true,
+ "upload_time": "2015-06-15T09:50:35",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/86/fd/cc8315be63a41fe000cce20482a917e874cdc1151e62cb0141f5e55f711e/psycopg2-2.6.1.tar.gz",
+ "md5_digest": "842b44f8c95517ed5b792081a2370da1",
+ "downloads": 3521176,
+ "filename": "psycopg2-2.6.1.tar.gz",
+ "packagetype": "sdist",
+ "path": "86/fd/cc8315be63a41fe000cce20482a917e874cdc1151e62cb0141f5e55f711e/psycopg2-2.6.1.tar.gz",
+ "size": 371373
+ }
+ ],
+ "2.6.2": [
+ {
+ "has_sig": false,
+ "upload_time": "2016-07-08T03:12:31",
+ "comment_text": "",
+ "python_version": "cp26",
+ "url": "https://pypi.org/packages/49/fe/edd5a96ece520bf6522e27360f0aa66305e8cafa177c3bf5d5418a6b0741/psycopg2-2.6.2-cp26-none-win32.whl",
+ "md5_digest": "24ece1e5ea08083289e564b2b864a5a6",
+ "downloads": 465,
+ "filename": "psycopg2-2.6.2-cp26-none-win32.whl",
+ "packagetype": "bdist_wheel",
+ "path": "49/fe/edd5a96ece520bf6522e27360f0aa66305e8cafa177c3bf5d5418a6b0741/psycopg2-2.6.2-cp26-none-win32.whl",
+ "size": 807955
+ },
+ {
+ "has_sig": false,
+ "upload_time": "2016-07-08T03:12:41",
+ "comment_text": "",
+ "python_version": "cp26",
+ "url": "https://pypi.org/packages/14/04/c449c231d35b1d26ebd902aea4f9237da744cd3a0bd9ff89caf616a6e6fc/psycopg2-2.6.2-cp26-none-win_amd64.whl",
+ "md5_digest": "3ee8bcfeefb573b7a68000bd25f73f43",
+ "downloads": 568,
+ "filename": "psycopg2-2.6.2-cp26-none-win_amd64.whl",
+ "packagetype": "bdist_wheel",
+ "path": "14/04/c449c231d35b1d26ebd902aea4f9237da744cd3a0bd9ff89caf616a6e6fc/psycopg2-2.6.2-cp26-none-win_amd64.whl",
+ "size": 1157090
+ },
+ {
+ "has_sig": false,
+ "upload_time": "2016-07-08T03:12:48",
+ "comment_text": "",
+ "python_version": "cp27",
+ "url": "https://pypi.org/packages/30/b9/629418a0fdc84506cfb9005ac066bb409b40661d2bfde6fc083d93237b27/psycopg2-2.6.2-cp27-none-win32.whl",
+ "md5_digest": "be33931d712a47275c3f4a373059f7ea",
+ "downloads": 4658,
+ "filename": "psycopg2-2.6.2-cp27-none-win32.whl",
+ "packagetype": "bdist_wheel",
+ "path": "30/b9/629418a0fdc84506cfb9005ac066bb409b40661d2bfde6fc083d93237b27/psycopg2-2.6.2-cp27-none-win32.whl",
+ "size": 807955
+ },
+ {
+ "has_sig": false,
+ "upload_time": "2016-07-08T03:12:57",
+ "comment_text": "",
+ "python_version": "cp27",
+ "url": "https://pypi.org/packages/a4/0e/29d29dceca6e465804ae612bc711a4741599ac849cf0a99acdbf53838581/psycopg2-2.6.2-cp27-none-win_amd64.whl",
+ "md5_digest": "08d618f1c5a4db211481e59102cc16f8",
+ "downloads": 4240,
+ "filename": "psycopg2-2.6.2-cp27-none-win_amd64.whl",
+ "packagetype": "bdist_wheel",
+ "path": "a4/0e/29d29dceca6e465804ae612bc711a4741599ac849cf0a99acdbf53838581/psycopg2-2.6.2-cp27-none-win_amd64.whl",
+ "size": 1157086
+ },
+ {
+ "has_sig": false,
+ "upload_time": "2016-07-08T03:13:07",
+ "comment_text": "",
+ "python_version": "cp32",
+ "url": "https://pypi.org/packages/ba/29/bb6c465a38f6ba070ad4f4b17797ccc345dcd2cd42eb2f262aa75d86fa52/psycopg2-2.6.2-cp32-none-win32.whl",
+ "md5_digest": "0e9dca689b2395dea2498b3b82923b37",
+ "downloads": 333,
+ "filename": "psycopg2-2.6.2-cp32-none-win32.whl",
+ "packagetype": "bdist_wheel",
+ "path": "ba/29/bb6c465a38f6ba070ad4f4b17797ccc345dcd2cd42eb2f262aa75d86fa52/psycopg2-2.6.2-cp32-none-win32.whl",
+ "size": 808593
+ },
+ {
+ "has_sig": false,
+ "upload_time": "2016-07-08T03:13:16",
+ "comment_text": "",
+ "python_version": "cp32",
+ "url": "https://pypi.org/packages/d3/bd/f989a3be8cd9fa696471ca399c005c903c3a4b840c419784fb27c0c62ae8/psycopg2-2.6.2-cp32-none-win_amd64.whl",
+ "md5_digest": "66243f1c0a3f0365489d84d0e9111e63",
+ "downloads": 339,
+ "filename": "psycopg2-2.6.2-cp32-none-win_amd64.whl",
+ "packagetype": "bdist_wheel",
+ "path": "d3/bd/f989a3be8cd9fa696471ca399c005c903c3a4b840c419784fb27c0c62ae8/psycopg2-2.6.2-cp32-none-win_amd64.whl",
+ "size": 1158092
+ },
+ {
+ "has_sig": false,
+ "upload_time": "2016-07-08T03:11:48",
+ "comment_text": "",
+ "python_version": "cp33",
+ "url": "https://pypi.org/packages/6c/b4/d5bf17145954a3c8e80e3601d8eaf486f058ae09688910f1f0a22cb6b1d2/psycopg2-2.6.2-cp33-none-win32.whl",
+ "md5_digest": "7d7dbd8e6203e2e757b46d77fcb30eee",
+ "downloads": 358,
+ "filename": "psycopg2-2.6.2-cp33-none-win32.whl",
+ "packagetype": "bdist_wheel",
+ "path": "6c/b4/d5bf17145954a3c8e80e3601d8eaf486f058ae09688910f1f0a22cb6b1d2/psycopg2-2.6.2-cp33-none-win32.whl",
+ "size": 812530
+ },
+ {
+ "has_sig": false,
+ "upload_time": "2016-07-08T03:11:56",
+ "comment_text": "",
+ "python_version": "cp33",
+ "url": "https://pypi.org/packages/2a/34/849e0491130bf2f67d72826ad64cfe8d9dc4e322b42ba99ab77dd96d970f/psycopg2-2.6.2-cp33-none-win_amd64.whl",
+ "md5_digest": "60816e4ffadd258f3bd1b5c3da62ecfe",
+ "downloads": 366,
+ "filename": "psycopg2-2.6.2-cp33-none-win_amd64.whl",
+ "packagetype": "bdist_wheel",
+ "path": "2a/34/849e0491130bf2f67d72826ad64cfe8d9dc4e322b42ba99ab77dd96d970f/psycopg2-2.6.2-cp33-none-win_amd64.whl",
+ "size": 1154446
+ },
+ {
+ "has_sig": false,
+ "upload_time": "2016-07-08T03:12:04",
+ "comment_text": "",
+ "python_version": "cp34",
+ "url": "https://pypi.org/packages/8f/80/20bdb48cfccaf31be57f7ae4b5165d7bb669cfaae5a42eaf00d55b2bf39b/psycopg2-2.6.2-cp34-none-win32.whl",
+ "md5_digest": "819bcec9a26fb1877090cf60faf5bfc4",
+ "downloads": 1040,
+ "filename": "psycopg2-2.6.2-cp34-none-win32.whl",
+ "packagetype": "bdist_wheel",
+ "path": "8f/80/20bdb48cfccaf31be57f7ae4b5165d7bb669cfaae5a42eaf00d55b2bf39b/psycopg2-2.6.2-cp34-none-win32.whl",
+ "size": 812387
+ },
+ {
+ "has_sig": false,
+ "upload_time": "2016-07-08T03:12:13",
+ "comment_text": "",
+ "python_version": "cp34",
+ "url": "https://pypi.org/packages/fe/23/c67030ab4a43655d10b62acc658829054a97a147819a81094b1e9673e592/psycopg2-2.6.2-cp34-none-win_amd64.whl",
+ "md5_digest": "26ca03d4f4f65c75a530824981a60df6",
+ "downloads": 1204,
+ "filename": "psycopg2-2.6.2-cp34-none-win_amd64.whl",
+ "packagetype": "bdist_wheel",
+ "path": "fe/23/c67030ab4a43655d10b62acc658829054a97a147819a81094b1e9673e592/psycopg2-2.6.2-cp34-none-win_amd64.whl",
+ "size": 1154539
+ },
+ {
+ "has_sig": false,
+ "upload_time": "2016-07-08T03:13:21",
+ "comment_text": "",
+ "python_version": "cp35",
+ "url": "https://pypi.org/packages/85/bb/7ab5d5b040d6c8a26180acb864f50c1887f27e02e9fb4e94f1f730a4e01b/psycopg2-2.6.2-cp35-none-win32.whl",
+ "md5_digest": "9355dc0c57491e4e42bc610428570994",
+ "downloads": 2932,
+ "filename": "psycopg2-2.6.2-cp35-none-win32.whl",
+ "packagetype": "bdist_wheel",
+ "path": "85/bb/7ab5d5b040d6c8a26180acb864f50c1887f27e02e9fb4e94f1f730a4e01b/psycopg2-2.6.2-cp35-none-win32.whl",
+ "size": 801274
+ },
+ {
+ "has_sig": false,
+ "upload_time": "2016-07-08T03:13:26",
+ "comment_text": "",
+ "python_version": "cp35",
+ "url": "https://pypi.org/packages/5e/45/de485228f46a2487da8e774fa2dbd772e7e03e65a3c31a322a224806e734/psycopg2-2.6.2-cp35-none-win_amd64.whl",
+ "md5_digest": "c8101dfc2a2c2e6eb7e2054c8c0208b2",
+ "downloads": 3340,
+ "filename": "psycopg2-2.6.2-cp35-none-win_amd64.whl",
+ "packagetype": "bdist_wheel",
+ "path": "5e/45/de485228f46a2487da8e774fa2dbd772e7e03e65a3c31a322a224806e734/psycopg2-2.6.2-cp35-none-win_amd64.whl",
+ "size": 1159852
+ },
+ {
+ "has_sig": false,
+ "upload_time": "2016-12-23T16:50:51",
+ "comment_text": "",
+ "python_version": "cp36",
+ "url": "https://pypi.org/packages/66/97/e8922a18a142195cfdbdfc9ec84a8d1a46b09edae24a150d79ea90e6b55b/psycopg2-2.6.2-cp36-cp36m-win32.whl",
+ "md5_digest": "be2016ebc0a83ef40d068baa25ee4f3f",
+ "downloads": 493,
+ "filename": "psycopg2-2.6.2-cp36-cp36m-win32.whl",
+ "packagetype": "bdist_wheel",
+ "path": "66/97/e8922a18a142195cfdbdfc9ec84a8d1a46b09edae24a150d79ea90e6b55b/psycopg2-2.6.2-cp36-cp36m-win32.whl",
+ "size": 802352
+ },
+ {
+ "has_sig": false,
+ "upload_time": "2016-12-23T16:50:54",
+ "comment_text": "",
+ "python_version": "cp36",
+ "url": "https://pypi.org/packages/b6/cb/b7ad5008df09b8392942db9a262435bda778457be4aaba5fc79ead1444b4/psycopg2-2.6.2-cp36-cp36m-win_amd64.whl",
+ "md5_digest": "a1cc2cbb0d9a9191c64640d5129402c3",
+ "downloads": 582,
+ "filename": "psycopg2-2.6.2-cp36-cp36m-win_amd64.whl",
+ "packagetype": "bdist_wheel",
+ "path": "b6/cb/b7ad5008df09b8392942db9a262435bda778457be4aaba5fc79ead1444b4/psycopg2-2.6.2-cp36-cp36m-win_amd64.whl",
+ "size": 1162079
+ },
+ {
+ "has_sig": true,
+ "upload_time": "2016-07-07T02:23:58",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/7b/a8/dc2d50a6f37c157459cd18bab381c8e6134b9381b50fbe969997b2ae7dbc/psycopg2-2.6.2.tar.gz",
+ "md5_digest": "4a392949ba31a378a18ed3e775a4693f",
+ "downloads": 1545062,
+ "filename": "psycopg2-2.6.2.tar.gz",
+ "packagetype": "sdist",
+ "path": "7b/a8/dc2d50a6f37c157459cd18bab381c8e6134b9381b50fbe969997b2ae7dbc/psycopg2-2.6.2.tar.gz",
+ "size": 376348
+ }
+ ],
+ "2.0.14": [
+ {
+ "has_sig": false,
+ "upload_time": "2010-10-19T15:29:17",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/e0/1c/f0843f50a69fba3db880e9b267d36f6709bbf31a36fc46b82f75e8975ede/psycopg2-2.0.14.tar.gz",
+ "md5_digest": "30136c7753acc9cbdc36cc5c2448fdee",
+ "downloads": 19521,
+ "filename": "psycopg2-2.0.14.tar.gz",
+ "packagetype": "sdist",
+ "path": "e0/1c/f0843f50a69fba3db880e9b267d36f6709bbf31a36fc46b82f75e8975ede/psycopg2-2.0.14.tar.gz",
+ "size": 491362
+ }
+ ],
+ "2.0.13": [
+ {
+ "has_sig": false,
+ "upload_time": "2010-10-19T15:31:38",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/3a/7a/968afcb86b1958ae963a3aaa42c561e3ed2c2d4a8b773622b03856a16248/psycopg2-2.0.13.tar.gz",
+ "md5_digest": "f520260595f4fcf035d26cfd57a75f19",
+ "downloads": 14083,
+ "filename": "psycopg2-2.0.13.tar.gz",
+ "packagetype": "sdist",
+ "path": "3a/7a/968afcb86b1958ae963a3aaa42c561e3ed2c2d4a8b773622b03856a16248/psycopg2-2.0.13.tar.gz",
+ "size": 258399
+ }
+ ],
+ "2.0.12": [
+ {
+ "has_sig": false,
+ "upload_time": "2010-10-19T15:33:16",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/6a/8d/ee5c330823d527a5cd14c833063f825211d7b5de6e4897f72e250c107d85/psycopg2-2.0.12.tar.gz",
+ "md5_digest": "5c8080d0d0568479f041bb8534caf1f8",
+ "downloads": 4001,
+ "filename": "psycopg2-2.0.12.tar.gz",
+ "packagetype": "sdist",
+ "path": "6a/8d/ee5c330823d527a5cd14c833063f825211d7b5de6e4897f72e250c107d85/psycopg2-2.0.12.tar.gz",
+ "size": 256169
+ }
+ ],
+ "2.0.11": [
+ {
+ "has_sig": false,
+ "upload_time": "2010-10-19T15:35:04",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/2d/d7/496da11d7c81971870ddd36800419c4f84e8f6208aac5eabedf9f7748729/psycopg2-2.0.11.tar.gz",
+ "md5_digest": "eec2a45bcea75a00cbf20a15ab1b8bae",
+ "downloads": 4052,
+ "filename": "psycopg2-2.0.11.tar.gz",
+ "packagetype": "sdist",
+ "path": "2d/d7/496da11d7c81971870ddd36800419c4f84e8f6208aac5eabedf9f7748729/psycopg2-2.0.11.tar.gz",
+ "size": 255260
+ }
+ ],
+ "2.0.10": [
+ {
+ "has_sig": false,
+ "upload_time": "2010-10-19T15:36:38",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/19/79/35c7596bab4456f3610c12ec542a94d51c6781ced587d1d85127210b879b/psycopg2-2.0.10.tar.gz",
+ "md5_digest": "2dc60d0fd90ad681e1e9106edef34e97",
+ "downloads": 5027,
+ "filename": "psycopg2-2.0.10.tar.gz",
+ "packagetype": "sdist",
+ "path": "19/79/35c7596bab4456f3610c12ec542a94d51c6781ced587d1d85127210b879b/psycopg2-2.0.10.tar.gz",
+ "size": 255995
+ }
+ ]
+ },
+ "urls": [
+ {
+ "has_sig": false,
+ "upload_time": "2016-07-08T03:12:31",
+ "comment_text": "",
+ "python_version": "cp26",
+ "url": "https://pypi.org/packages/49/fe/edd5a96ece520bf6522e27360f0aa66305e8cafa177c3bf5d5418a6b0741/psycopg2-2.6.2-cp26-none-win32.whl",
+ "md5_digest": "24ece1e5ea08083289e564b2b864a5a6",
+ "downloads": 465,
+ "filename": "psycopg2-2.6.2-cp26-none-win32.whl",
+ "packagetype": "bdist_wheel",
+ "path": "49/fe/edd5a96ece520bf6522e27360f0aa66305e8cafa177c3bf5d5418a6b0741/psycopg2-2.6.2-cp26-none-win32.whl",
+ "size": 807955
+ },
+ {
+ "has_sig": false,
+ "upload_time": "2016-07-08T03:12:41",
+ "comment_text": "",
+ "python_version": "cp26",
+ "url": "https://pypi.org/packages/14/04/c449c231d35b1d26ebd902aea4f9237da744cd3a0bd9ff89caf616a6e6fc/psycopg2-2.6.2-cp26-none-win_amd64.whl",
+ "md5_digest": "3ee8bcfeefb573b7a68000bd25f73f43",
+ "downloads": 568,
+ "filename": "psycopg2-2.6.2-cp26-none-win_amd64.whl",
+ "packagetype": "bdist_wheel",
+ "path": "14/04/c449c231d35b1d26ebd902aea4f9237da744cd3a0bd9ff89caf616a6e6fc/psycopg2-2.6.2-cp26-none-win_amd64.whl",
+ "size": 1157090
+ },
+ {
+ "has_sig": false,
+ "upload_time": "2016-07-08T03:12:48",
+ "comment_text": "",
+ "python_version": "cp27",
+ "url": "https://pypi.org/packages/30/b9/629418a0fdc84506cfb9005ac066bb409b40661d2bfde6fc083d93237b27/psycopg2-2.6.2-cp27-none-win32.whl",
+ "md5_digest": "be33931d712a47275c3f4a373059f7ea",
+ "downloads": 4658,
+ "filename": "psycopg2-2.6.2-cp27-none-win32.whl",
+ "packagetype": "bdist_wheel",
+ "path": "30/b9/629418a0fdc84506cfb9005ac066bb409b40661d2bfde6fc083d93237b27/psycopg2-2.6.2-cp27-none-win32.whl",
+ "size": 807955
+ },
+ {
+ "has_sig": false,
+ "upload_time": "2016-07-08T03:12:57",
+ "comment_text": "",
+ "python_version": "cp27",
+ "url": "https://pypi.org/packages/a4/0e/29d29dceca6e465804ae612bc711a4741599ac849cf0a99acdbf53838581/psycopg2-2.6.2-cp27-none-win_amd64.whl",
+ "md5_digest": "08d618f1c5a4db211481e59102cc16f8",
+ "downloads": 4240,
+ "filename": "psycopg2-2.6.2-cp27-none-win_amd64.whl",
+ "packagetype": "bdist_wheel",
+ "path": "a4/0e/29d29dceca6e465804ae612bc711a4741599ac849cf0a99acdbf53838581/psycopg2-2.6.2-cp27-none-win_amd64.whl",
+ "size": 1157086
+ },
+ {
+ "has_sig": false,
+ "upload_time": "2016-07-08T03:13:07",
+ "comment_text": "",
+ "python_version": "cp32",
+ "url": "https://pypi.org/packages/ba/29/bb6c465a38f6ba070ad4f4b17797ccc345dcd2cd42eb2f262aa75d86fa52/psycopg2-2.6.2-cp32-none-win32.whl",
+ "md5_digest": "0e9dca689b2395dea2498b3b82923b37",
+ "downloads": 333,
+ "filename": "psycopg2-2.6.2-cp32-none-win32.whl",
+ "packagetype": "bdist_wheel",
+ "path": "ba/29/bb6c465a38f6ba070ad4f4b17797ccc345dcd2cd42eb2f262aa75d86fa52/psycopg2-2.6.2-cp32-none-win32.whl",
+ "size": 808593
+ },
+ {
+ "has_sig": false,
+ "upload_time": "2016-07-08T03:13:16",
+ "comment_text": "",
+ "python_version": "cp32",
+ "url": "https://pypi.org/packages/d3/bd/f989a3be8cd9fa696471ca399c005c903c3a4b840c419784fb27c0c62ae8/psycopg2-2.6.2-cp32-none-win_amd64.whl",
+ "md5_digest": "66243f1c0a3f0365489d84d0e9111e63",
+ "downloads": 339,
+ "filename": "psycopg2-2.6.2-cp32-none-win_amd64.whl",
+ "packagetype": "bdist_wheel",
+ "path": "d3/bd/f989a3be8cd9fa696471ca399c005c903c3a4b840c419784fb27c0c62ae8/psycopg2-2.6.2-cp32-none-win_amd64.whl",
+ "size": 1158092
+ },
+ {
+ "has_sig": false,
+ "upload_time": "2016-07-08T03:11:48",
+ "comment_text": "",
+ "python_version": "cp33",
+ "url": "https://pypi.org/packages/6c/b4/d5bf17145954a3c8e80e3601d8eaf486f058ae09688910f1f0a22cb6b1d2/psycopg2-2.6.2-cp33-none-win32.whl",
+ "md5_digest": "7d7dbd8e6203e2e757b46d77fcb30eee",
+ "downloads": 358,
+ "filename": "psycopg2-2.6.2-cp33-none-win32.whl",
+ "packagetype": "bdist_wheel",
+ "path": "6c/b4/d5bf17145954a3c8e80e3601d8eaf486f058ae09688910f1f0a22cb6b1d2/psycopg2-2.6.2-cp33-none-win32.whl",
+ "size": 812530
+ },
+ {
+ "has_sig": false,
+ "upload_time": "2016-07-08T03:11:56",
+ "comment_text": "",
+ "python_version": "cp33",
+ "url": "https://pypi.org/packages/2a/34/849e0491130bf2f67d72826ad64cfe8d9dc4e322b42ba99ab77dd96d970f/psycopg2-2.6.2-cp33-none-win_amd64.whl",
+ "md5_digest": "60816e4ffadd258f3bd1b5c3da62ecfe",
+ "downloads": 366,
+ "filename": "psycopg2-2.6.2-cp33-none-win_amd64.whl",
+ "packagetype": "bdist_wheel",
+ "path": "2a/34/849e0491130bf2f67d72826ad64cfe8d9dc4e322b42ba99ab77dd96d970f/psycopg2-2.6.2-cp33-none-win_amd64.whl",
+ "size": 1154446
+ },
+ {
+ "has_sig": false,
+ "upload_time": "2016-07-08T03:12:04",
+ "comment_text": "",
+ "python_version": "cp34",
+ "url": "https://pypi.org/packages/8f/80/20bdb48cfccaf31be57f7ae4b5165d7bb669cfaae5a42eaf00d55b2bf39b/psycopg2-2.6.2-cp34-none-win32.whl",
+ "md5_digest": "819bcec9a26fb1877090cf60faf5bfc4",
+ "downloads": 1040,
+ "filename": "psycopg2-2.6.2-cp34-none-win32.whl",
+ "packagetype": "bdist_wheel",
+ "path": "8f/80/20bdb48cfccaf31be57f7ae4b5165d7bb669cfaae5a42eaf00d55b2bf39b/psycopg2-2.6.2-cp34-none-win32.whl",
+ "size": 812387
+ },
+ {
+ "has_sig": false,
+ "upload_time": "2016-07-08T03:12:13",
+ "comment_text": "",
+ "python_version": "cp34",
+ "url": "https://pypi.org/packages/fe/23/c67030ab4a43655d10b62acc658829054a97a147819a81094b1e9673e592/psycopg2-2.6.2-cp34-none-win_amd64.whl",
+ "md5_digest": "26ca03d4f4f65c75a530824981a60df6",
+ "downloads": 1204,
+ "filename": "psycopg2-2.6.2-cp34-none-win_amd64.whl",
+ "packagetype": "bdist_wheel",
+ "path": "fe/23/c67030ab4a43655d10b62acc658829054a97a147819a81094b1e9673e592/psycopg2-2.6.2-cp34-none-win_amd64.whl",
+ "size": 1154539
+ },
+ {
+ "has_sig": false,
+ "upload_time": "2016-07-08T03:13:21",
+ "comment_text": "",
+ "python_version": "cp35",
+ "url": "https://pypi.org/packages/85/bb/7ab5d5b040d6c8a26180acb864f50c1887f27e02e9fb4e94f1f730a4e01b/psycopg2-2.6.2-cp35-none-win32.whl",
+ "md5_digest": "9355dc0c57491e4e42bc610428570994",
+ "downloads": 2932,
+ "filename": "psycopg2-2.6.2-cp35-none-win32.whl",
+ "packagetype": "bdist_wheel",
+ "path": "85/bb/7ab5d5b040d6c8a26180acb864f50c1887f27e02e9fb4e94f1f730a4e01b/psycopg2-2.6.2-cp35-none-win32.whl",
+ "size": 801274
+ },
+ {
+ "has_sig": false,
+ "upload_time": "2016-07-08T03:13:26",
+ "comment_text": "",
+ "python_version": "cp35",
+ "url": "https://pypi.org/packages/5e/45/de485228f46a2487da8e774fa2dbd772e7e03e65a3c31a322a224806e734/psycopg2-2.6.2-cp35-none-win_amd64.whl",
+ "md5_digest": "c8101dfc2a2c2e6eb7e2054c8c0208b2",
+ "downloads": 3340,
+ "filename": "psycopg2-2.6.2-cp35-none-win_amd64.whl",
+ "packagetype": "bdist_wheel",
+ "path": "5e/45/de485228f46a2487da8e774fa2dbd772e7e03e65a3c31a322a224806e734/psycopg2-2.6.2-cp35-none-win_amd64.whl",
+ "size": 1159852
+ },
+ {
+ "has_sig": false,
+ "upload_time": "2016-12-23T16:50:51",
+ "comment_text": "",
+ "python_version": "cp36",
+ "url": "https://pypi.org/packages/66/97/e8922a18a142195cfdbdfc9ec84a8d1a46b09edae24a150d79ea90e6b55b/psycopg2-2.6.2-cp36-cp36m-win32.whl",
+ "md5_digest": "be2016ebc0a83ef40d068baa25ee4f3f",
+ "downloads": 493,
+ "filename": "psycopg2-2.6.2-cp36-cp36m-win32.whl",
+ "packagetype": "bdist_wheel",
+ "path": "66/97/e8922a18a142195cfdbdfc9ec84a8d1a46b09edae24a150d79ea90e6b55b/psycopg2-2.6.2-cp36-cp36m-win32.whl",
+ "size": 802352
+ },
+ {
+ "has_sig": false,
+ "upload_time": "2016-12-23T16:50:54",
+ "comment_text": "",
+ "python_version": "cp36",
+ "url": "https://pypi.org/packages/b6/cb/b7ad5008df09b8392942db9a262435bda778457be4aaba5fc79ead1444b4/psycopg2-2.6.2-cp36-cp36m-win_amd64.whl",
+ "md5_digest": "a1cc2cbb0d9a9191c64640d5129402c3",
+ "downloads": 582,
+ "filename": "psycopg2-2.6.2-cp36-cp36m-win_amd64.whl",
+ "packagetype": "bdist_wheel",
+ "path": "b6/cb/b7ad5008df09b8392942db9a262435bda778457be4aaba5fc79ead1444b4/psycopg2-2.6.2-cp36-cp36m-win_amd64.whl",
+ "size": 1162079
+ },
+ {
+ "has_sig": true,
+ "upload_time": "2016-07-07T02:23:58",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/7b/a8/dc2d50a6f37c157459cd18bab381c8e6134b9381b50fbe969997b2ae7dbc/psycopg2-2.6.2.tar.gz",
+ "md5_digest": "4a392949ba31a378a18ed3e775a4693f",
+ "downloads": 1545062,
+ "filename": "psycopg2-2.6.2.tar.gz",
+ "packagetype": "sdist",
+ "path": "7b/a8/dc2d50a6f37c157459cd18bab381c8e6134b9381b50fbe969997b2ae7dbc/psycopg2-2.6.2.tar.gz",
+ "size": 376348
+ }
+ ]
+}
diff --git a/uv/spec/fixtures/pypi/pypi_response_pendulum.json b/uv/spec/fixtures/pypi/pypi_response_pendulum.json
new file mode 100644
index 00000000000..a011e124d64
--- /dev/null
+++ b/uv/spec/fixtures/pypi/pypi_response_pendulum.json
@@ -0,0 +1,6147 @@
+{
+ "info": {
+ "author": "Sébastien Eustace",
+ "author_email": "sebastien@eustace.io",
+ "bugtrack_url": null,
+ "classifiers": [
+ "License :: OSI Approved :: MIT License",
+ "Programming Language :: Python :: 2",
+ "Programming Language :: Python :: 2.7",
+ "Programming Language :: Python :: 3",
+ "Programming Language :: Python :: 3.4",
+ "Programming Language :: Python :: 3.5",
+ "Programming Language :: Python :: 3.6",
+ "Programming Language :: Python :: 3.7"
+ ],
+ "description": "Pendulum\n########\n\n.. image:: https://img.shields.io/pypi/v/pendulum.svg\n :target: https://pypi.org/pypi/pendulum\n\n.. image:: https://img.shields.io/pypi/l/pendulum.svg\n :target: https://pypi.org/pypi/pendulum\n\n.. image:: https://img.shields.io/codecov/c/github/sdispater/pendulum/master.svg\n :target: https://codecov.io/gh/sdispater/pendulum/branch/master\n\n.. image:: https://travis-ci.org/sdispater/pendulum.svg\n :alt: Pendulum Build status\n :target: https://travis-ci.org/sdispater/pendulum\n\nPython datetimes made easy.\n\nSupports Python **2.7** and **3.4+**.\n\n\n.. code-block:: python\n\n >>> import pendulum\n\n >>> now_in_paris = pendulum.now('Europe/Paris')\n >>> now_in_paris\n '2016-07-04T00:49:58.502116+02:00'\n\n # Seamless timezone switching\n >>> now_in_paris.in_timezone('UTC')\n '2016-07-03T22:49:58.502116+00:00'\n\n >>> tomorrow = pendulum.now().add(days=1)\n >>> last_week = pendulum.now().subtract(weeks=1)\n\n >>> past = pendulum.now().subtract(minutes=2)\n >>> past.diff_for_humans()\n >>> '2 minutes ago'\n\n >>> delta = past - last_week\n >>> delta.hours\n 23\n >>> delta.in_words(locale='en')\n '6 days 23 hours 58 minutes'\n\n # Proper handling of datetime normalization\n >>> pendulum.datetime(2013, 3, 31, 2, 30, tz='Europe/Paris')\n '2013-03-31T03:30:00+02:00' # 2:30 does not exist (Skipped time)\n\n # Proper handling of dst transitions\n >>> just_before = pendulum.datetime(2013, 3, 31, 1, 59, 59, 999999, tz='Europe/Paris')\n '2013-03-31T01:59:59.999999+01:00'\n >>> just_before.add(microseconds=1)\n '2013-03-31T03:00:00+02:00'\n\n\nWhy Pendulum?\n=============\n\nNative ``datetime`` instances are enough for basic cases but when you face more complex use-cases\nthey often show limitations and are not so intuitive to work with.\n``Pendulum`` provides a cleaner and more easy to use API while still relying on the standard library.\nSo it's still ``datetime`` but better.\n\nUnlike other datetime libraries for Python, Pendulum is a drop-in replacement\nfor the standard ``datetime`` class (it inherits from it), so, basically, you can replace all your ``datetime``\ninstances by ``DateTime`` instances in you code (exceptions exist for libraries that check\nthe type of the objects by using the ``type`` function like ``sqlite3`` or ``PyMySQL`` for instance).\n\nIt also removes the notion of naive datetimes: each ``Pendulum`` instance is timezone-aware\nand by default in ``UTC`` for ease of use.\n\nPendulum also improves the standard ``timedelta`` class by providing more intuitive methods and properties.\n\n\nWhy not Arrow?\n==============\n\nArrow is the most popular datetime library for Python right now, however its behavior\nand API can be erratic and unpredictable. The ``get()`` method can receive pretty much anything\nand it will try its best to return something while silently failing to handle some cases:\n\n.. code-block:: python\n\n arrow.get('2016-1-17')\n # \n\n pendulum.parse('2016-1-17')\n # \n\n arrow.get('20160413')\n # \n\n pendulum.parse('20160413')\n # \n\n arrow.get('2016-W07-5')\n # \n\n pendulum.parse('2016-W07-5')\n # \n\n # Working with DST\n just_before = arrow.Arrow(2013, 3, 31, 1, 59, 59, 999999, 'Europe/Paris')\n just_after = just_before.replace(microseconds=1)\n '2013-03-31T02:00:00+02:00'\n # Should be 2013-03-31T03:00:00+02:00\n\n (just_after.to('utc') - just_before.to('utc')).total_seconds()\n -3599.999999\n # Should be 1e-06\n\n just_before = pendulum.datetime(2013, 3, 31, 1, 59, 59, 999999, 'Europe/Paris')\n just_after = just_before.add(microseconds=1)\n '2013-03-31T03:00:00+02:00'\n\n (just_after.in_timezone('utc') - just_before.in_timezone('utc')).total_seconds()\n 1e-06\n\nThose are a few examples showing that Arrow cannot always be trusted to have a consistent\nbehavior with the data you are passing to it.\n\n\nLimitations\n===========\n\nEven though the ``DateTime`` class is a subclass of ``datetime`` there are some rare cases where\nit can't replace the native class directly. Here is a list (non-exhaustive) of the reported cases with\na possible solution, if any:\n\n* ``sqlite3`` will use the ``type()`` function to determine the type of the object by default. To work around it you can register a new adapter:\n\n.. code-block:: python\n\n from pendulum import DateTime\n from sqlite3 import register_adapter\n\n register_adapter(DateTime, lambda val: val.isoformat(' '))\n\n* ``mysqlclient`` (former ``MySQLdb``) and ``PyMySQL`` will use the ``type()`` function to determine the type of the object by default. To work around it you can register a new adapter:\n\n.. code-block:: python\n\n import MySQLdb.converters\n import pymysql.converters\n\n from pendulum import DateTime\n\n MySQLdb.converters.conversions[DateTime] = MySQLdb.converters.DateTime2literal\n pymysql.converters.conversions[DateTime] = pymysql.converters.escape_datetime\n\n* ``django`` will use the ``isoformat()`` method to store datetimes in the database. However since ``pendulum`` is always timezone aware the offset information will always be returned by ``isoformat()`` raising an error, at least for MySQL databases. To work around it you can either create your own ``DateTimeField`` or use the previous workaround for ``MySQLdb``:\n\n.. code-block:: python\n\n from django.db.models import DateTimeField as BaseDateTimeField\n from pendulum import DateTime\n\n\n class DateTimeField(BaseDateTimeField):\n\n def value_to_string(self, obj):\n val = self.value_from_object(obj)\n\n if isinstance(value, DateTime):\n return value.to_datetime_string()\n\n return '' if val is None else val.isoformat()\n\n\nResources\n=========\n\n* `Official Website `_\n* `Documentation `_\n* `Issue Tracker `_\n\n\nContributing\n============\n\nContributions are welcome, especially with localization.\n\nGetting started\n---------------\n\nTo work on the Pendulum codebase, you'll want to clone the project locally\nand install the required depedendencies via `poetry `_.\n\n.. code-block:: bash\n\n $ git clone git@github.com:sdispater/pendulum.git\n $ poetry install\n\nLocalization\n------------\n\nIf you want to help with localization, there are two different cases: the locale already exists\nor not.\n\nIf the locale does not exist you will need to create it by using the ``clock`` utility:\n\n.. code-block:: bash\n\n ./clock locale:create \n\nIt will generate a directory in ``pendulum/locales`` named after your locale, with the following\nstructure:\n\n.. code-block:: text\n\n /\n - custom.py\n - locale.py\n\nThe ``locale.py`` file must not be modified. It contains the translations provided by\nthe CLDR database.\n\nThe ``custom.py`` file is the one you want to modify. It contains the data needed\nby Pendulum that are not provided by the CLDR database. You can take the `en `_\ndata as a reference to see which data is needed.\n\nYou should also add tests for the created or modified locale.\n",
+ "description_content_type": "text/x-rst",
+ "docs_url": null,
+ "download_url": "",
+ "downloads": {
+ "last_day": -1,
+ "last_month": -1,
+ "last_week": -1
+ },
+ "home_page": "https://pendulum.eustace.io",
+ "keywords": "datetime,date,time",
+ "license": "MIT",
+ "maintainer": "Sébastien Eustace",
+ "maintainer_email": "sebastien@eustace.io",
+ "name": "pendulum",
+ "package_url": "https://pypi.org/project/pendulum/",
+ "platform": "",
+ "project_url": "https://pypi.org/project/pendulum/",
+ "project_urls": {
+ "Homepage": "https://pendulum.eustace.io"
+ },
+ "release_url": "https://pypi.org/project/pendulum/2.0.3/",
+ "requires_dist": [
+ "typing (>=3.6,<4.0); python_version < \"3.5\"",
+ "pytzdata (>=2018.3)",
+ "python-dateutil (>=2.6,<3.0)"
+ ],
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "summary": "Python datetimes made easy",
+ "version": "2.0.3"
+ },
+ "last_serial": 4117886,
+ "releases": {
+ "0.1": [
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "a5b8dac262efb51a27b0815486d2829a",
+ "sha256": "7c2d47136f0557453b45ef9dcf43f9af3d333f5aef585a1f2553d2a0ed6b0d93"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.1.tar.gz",
+ "has_sig": false,
+ "md5_digest": "a5b8dac262efb51a27b0815486d2829a",
+ "packagetype": "sdist",
+ "python_version": "source",
+ "requires_python": null,
+ "size": 21875,
+ "upload_time": "2016-07-04T05:00:38",
+ "url": "https://files.pythonhosted.org/packages/75/c4/f9bb02e08f934f5e8b3ac7ddfe51970efbb7044b9aa8483aa261d83464bd/pendulum-0.1.tar.gz"
+ }
+ ],
+ "0.1.1": [
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "5c55c4d78618828d488c38b61de3c651",
+ "sha256": "a3827184ed23c940dd38a1d11c69861350e8cfc98affb4a5d0e546bec433c214"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.1.1.tar.gz",
+ "has_sig": false,
+ "md5_digest": "5c55c4d78618828d488c38b61de3c651",
+ "packagetype": "sdist",
+ "python_version": "source",
+ "requires_python": null,
+ "size": 22151,
+ "upload_time": "2016-07-04T16:35:09",
+ "url": "https://files.pythonhosted.org/packages/1e/17/92ed7366519edae606c5189847bf78e77bfc4b29752c2a82cef9159235ed/pendulum-0.1.1.tar.gz"
+ }
+ ],
+ "0.2": [
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "3f3de9f2892a0831cc339ca05afd5e98",
+ "sha256": "d8cf6d99650e3b132d4d3c2448a646020d750b04b68072d10a8a2edd22b4d789"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.2.tar.gz",
+ "has_sig": false,
+ "md5_digest": "3f3de9f2892a0831cc339ca05afd5e98",
+ "packagetype": "sdist",
+ "python_version": "source",
+ "requires_python": null,
+ "size": 22788,
+ "upload_time": "2016-07-04T22:39:48",
+ "url": "https://files.pythonhosted.org/packages/c2/bd/9b3d03fbc1aad46cb6a361f5a73987bb862b380b2e3cba1ca29d3a014598/pendulum-0.2.tar.gz"
+ }
+ ],
+ "0.3": [
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "ab826c07dfb7eba4615c73051261ca41",
+ "sha256": "6fa6159bba744aeb07b0bd08ffd297ac26cacf63f3ded9032f36471e3031f0f2"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.3.tar.gz",
+ "has_sig": false,
+ "md5_digest": "ab826c07dfb7eba4615c73051261ca41",
+ "packagetype": "sdist",
+ "python_version": "source",
+ "requires_python": null,
+ "size": 24052,
+ "upload_time": "2016-07-11T04:04:41",
+ "url": "https://files.pythonhosted.org/packages/91/b7/447c7c7382c4647c751f805ef2e4ff8d98f970151b0febdc555eb202dca8/pendulum-0.3.tar.gz"
+ }
+ ],
+ "0.3.1": [
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "066d6397ea3530a7deb0373c5b6cafc4",
+ "sha256": "a2716aad7422126715d16d1a7b02eb80760279e0b30a58e0938fe99b8edadb3c"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.3.1-py2.py3-none-any.whl",
+ "has_sig": false,
+ "md5_digest": "066d6397ea3530a7deb0373c5b6cafc4",
+ "packagetype": "bdist_wheel",
+ "python_version": "any",
+ "requires_python": null,
+ "size": 39624,
+ "upload_time": "2016-07-13T16:38:14",
+ "url": "https://files.pythonhosted.org/packages/81/f8/380b78cc02c49add1f531e3ca859b97b85057134f7404817a1cf8ef0a847/pendulum-0.3.1-py2.py3-none-any.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "139e12f07adfe0cfb65dbd1e0bd859dc",
+ "sha256": "b9357439aae2f12dbdc3424fff009d12afbd69a713ec9de69dd3b129b4f9f073"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.3.1.tar.gz",
+ "has_sig": false,
+ "md5_digest": "139e12f07adfe0cfb65dbd1e0bd859dc",
+ "packagetype": "sdist",
+ "python_version": "source",
+ "requires_python": null,
+ "size": 24133,
+ "upload_time": "2016-07-13T16:30:03",
+ "url": "https://files.pythonhosted.org/packages/b5/93/17532d124ee1c5d719fb4cfb7be985ae58ada3b2f4a88b14d6cdbbca5c45/pendulum-0.3.1.tar.gz"
+ }
+ ],
+ "0.4": [
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "2f5dde5bf97e20df68d9b386e021431a",
+ "sha256": "e7bfe713c4b26fed5e9b2e679a165ca34ffa1acb4b76a6e0eed570331971fa2b"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.4-py2.py3-none-any.whl",
+ "has_sig": false,
+ "md5_digest": "2f5dde5bf97e20df68d9b386e021431a",
+ "packagetype": "bdist_wheel",
+ "python_version": "any",
+ "requires_python": null,
+ "size": 58043,
+ "upload_time": "2016-07-25T23:00:11",
+ "url": "https://files.pythonhosted.org/packages/11/97/bcec6ccd95bcd0b3f79875f45e2d2406aeabdc98e2127d733ec6459ce8bd/pendulum-0.4-py2.py3-none-any.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "25b7d50b7f2a29c0d8aa7716856f3147",
+ "sha256": "9063975b7f514d6b98f1fc58843ce8813df0e4d39b592ee0760d96700fec9033"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.4.tar.gz",
+ "has_sig": false,
+ "md5_digest": "25b7d50b7f2a29c0d8aa7716856f3147",
+ "packagetype": "sdist",
+ "python_version": "source",
+ "requires_python": null,
+ "size": 35969,
+ "upload_time": "2016-07-25T22:58:11",
+ "url": "https://files.pythonhosted.org/packages/57/50/2c73febd9a33fedc63d33be954e92686c5e5d1b86ac69ba1483c549e5e4b/pendulum-0.4.tar.gz"
+ }
+ ],
+ "0.5": [
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "53278d1d72a6d1d8ac3340aa2c05fd43",
+ "sha256": "f560198a79e272b2ec1710c9c2b818ec302b53f8a7d0342cb371a649929af183"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.5.tar.gz",
+ "has_sig": false,
+ "md5_digest": "53278d1d72a6d1d8ac3340aa2c05fd43",
+ "packagetype": "sdist",
+ "python_version": "source",
+ "requires_python": null,
+ "size": 70035,
+ "upload_time": "2016-08-15T20:04:33",
+ "url": "https://files.pythonhosted.org/packages/4c/f1/eb9b5e1b8046918c766352b8e2a86bd7933e37275cda076b249b764f3c55/pendulum-0.5.tar.gz"
+ }
+ ],
+ "0.5.1": [
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "d577e0420483d5fd72e2bd8959b26784",
+ "sha256": "b55cadc4438254f5ef4da9a73abbd9fb6723731e275592bb0e0035fd8251210d"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.5.1-cp27-cp27m-macosx_10_11_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "d577e0420483d5fd72e2bd8959b26784",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": null,
+ "size": 110071,
+ "upload_time": "2016-08-18T20:09:47",
+ "url": "https://files.pythonhosted.org/packages/03/72/98e0600cb7ac6f09f2884d794ba3c09e26f5373a71a600dc7857998fa89d/pendulum-0.5.1-cp27-cp27m-macosx_10_11_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "004da9149f489cdf2774da648d990c83",
+ "sha256": "3729ef58c32dabc7075447cd9915a661eafcd004c2f24fb589fb1b7924d83d83"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.5.1-cp27-cp27m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "004da9149f489cdf2774da648d990c83",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": null,
+ "size": 143026,
+ "upload_time": "2016-08-18T19:50:22",
+ "url": "https://files.pythonhosted.org/packages/ff/93/b2ef10238f3243e63c96f4fbbf27e0636e415ba3791bdffb17ee7086c02b/pendulum-0.5.1-cp27-cp27m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "c869be46f8581ba783fd0dde6da77ad3",
+ "sha256": "782e93cced9439a7225345afb523557525fa3d2a21bf0a31cd1415da7ff336d0"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.5.1-cp27-cp27m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "c869be46f8581ba783fd0dde6da77ad3",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": null,
+ "size": 146428,
+ "upload_time": "2016-08-18T19:47:43",
+ "url": "https://files.pythonhosted.org/packages/b5/ab/f41e4344c6272f3971185147f60b2121180d6304002ff894ea9e7ac50d52/pendulum-0.5.1-cp27-cp27m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "af8a95a090bba56bc8f9524495e49ae6",
+ "sha256": "fdeaa83794b6f78c97ca4d4b7bd23b799d51d1ea81b34e45ba82a6fd792eb7fb"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.5.1-cp35-cp35m-macosx_10_11_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "af8a95a090bba56bc8f9524495e49ae6",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": null,
+ "size": 110185,
+ "upload_time": "2016-08-18T20:09:36",
+ "url": "https://files.pythonhosted.org/packages/29/e3/3d0c9b6fa68c3eab9e10913159493f5d4b45838f2c0ff0e8b6abc09259a3/pendulum-0.5.1-cp35-cp35m-macosx_10_11_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "c9fe668d0bfccb09243c3a37820c018d",
+ "sha256": "7c83245dd464c4b09591db222984b4a52b667f4abc419a50c16d87e40fd5078f"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.5.1-cp35-cp35m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "c9fe668d0bfccb09243c3a37820c018d",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": null,
+ "size": 146236,
+ "upload_time": "2016-08-18T19:50:33",
+ "url": "https://files.pythonhosted.org/packages/c6/f9/54e13aaadc8f82af8619448f16df0b236ebca7768923966cd031bad98b63/pendulum-0.5.1-cp35-cp35m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "ccef715458de14311599dc9c449265e4",
+ "sha256": "2becc6f723342c1bfa9d40d27052a80076228831f5f9ee1075bc3030586d7851"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.5.1-cp35-cp35m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "ccef715458de14311599dc9c449265e4",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": null,
+ "size": 148451,
+ "upload_time": "2016-08-18T19:47:47",
+ "url": "https://files.pythonhosted.org/packages/e9/f5/819c6ab71077680bdd0ae007731c806f90e46904874f59df99e9ab9a32f4/pendulum-0.5.1-cp35-cp35m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "bcbac6f8f698d56b8fa793764fda0c85",
+ "sha256": "59bdb2ef8e5f08c8c0544fc5a9295d90497e86d5b598de719995efbd138d8f8e"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.5.1.tar.gz",
+ "has_sig": false,
+ "md5_digest": "bcbac6f8f698d56b8fa793764fda0c85",
+ "packagetype": "sdist",
+ "python_version": "source",
+ "requires_python": null,
+ "size": 70082,
+ "upload_time": "2016-08-18T16:15:08",
+ "url": "https://files.pythonhosted.org/packages/0a/25/4a72c49bf62957e56ad070553c526f8a8617f8b9da94eb900a95051d5062/pendulum-0.5.1.tar.gz"
+ }
+ ],
+ "0.5.2": [
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "0387db8509f307984de1faa35fcbcee0",
+ "sha256": "7a3018f0f420a8d99853527fffc73066126350ed1983bc51c15413814f1721bb"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.5.2-cp27-cp27m-macosx_10_11_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "0387db8509f307984de1faa35fcbcee0",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": null,
+ "size": 111046,
+ "upload_time": "2016-08-22T17:11:55",
+ "url": "https://files.pythonhosted.org/packages/bf/12/97469c3398d7abdcd160ce630a857f5e59ac1a2dfcfef37e3d860ffc6c12/pendulum-0.5.2-cp27-cp27m-macosx_10_11_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "15e58650e2aefff966edaa373f3efef3",
+ "sha256": "2d4d3be2771098f6b430013b86ce7b14d0c99f85f808eed49257acf5d61cebf6"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.5.2-cp27-cp27m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "15e58650e2aefff966edaa373f3efef3",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": null,
+ "size": 144008,
+ "upload_time": "2016-08-22T17:08:09",
+ "url": "https://files.pythonhosted.org/packages/84/ac/f8156124583a48bcf5d309b497feb3285ba1f75becb924b335a22eeb9013/pendulum-0.5.2-cp27-cp27m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "8b232cf1666bee9b2b93bc0d2ef8692f",
+ "sha256": "da1c9a5aa0c442a621fb34440273f39917618fbe5edc74d3eaadf6727198ca1e"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.5.2-cp27-cp27m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "8b232cf1666bee9b2b93bc0d2ef8692f",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": null,
+ "size": 147394,
+ "upload_time": "2016-08-22T16:44:37",
+ "url": "https://files.pythonhosted.org/packages/31/09/8b9e2d54cf20b06fae951e1efe1772245074a3305819106e5c5c1a9ff079/pendulum-0.5.2-cp27-cp27m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "626ffdfc0daa9d71cc45dca340ed4de4",
+ "sha256": "d351fe559cc1b567c7d1a5897a5772a66dbad2b4500d289b2c7a6b05f466beb1"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.5.2-cp35-cp35m-macosx_10_11_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "626ffdfc0daa9d71cc45dca340ed4de4",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": null,
+ "size": 111152,
+ "upload_time": "2016-08-22T17:10:55",
+ "url": "https://files.pythonhosted.org/packages/26/e1/bf9d4a93408a3b0dd122e6c451ac2eb229921e67ceacf67a313e69e50950/pendulum-0.5.2-cp35-cp35m-macosx_10_11_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "ed68ec85fec433de4cbadcb2c63f524f",
+ "sha256": "8900e010bc4283d1f8fdc6def60e2594c73b5726e0102e73105ba076f634cebe"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.5.2-cp35-cp35m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "ed68ec85fec433de4cbadcb2c63f524f",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": null,
+ "size": 147204,
+ "upload_time": "2016-08-22T17:08:13",
+ "url": "https://files.pythonhosted.org/packages/60/3b/d010172cdabfeaf65361222b41242698912be2bd07c4fafa1e8ee418f976/pendulum-0.5.2-cp35-cp35m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "dfefe74833439c2166557e9659c02748",
+ "sha256": "e51144fcf7a09ab82f05a177f791b1011ed8e5df72e997351d8ff39b11477e7c"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.5.2-cp35-cp35m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "dfefe74833439c2166557e9659c02748",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": null,
+ "size": 149431,
+ "upload_time": "2016-08-22T16:44:41",
+ "url": "https://files.pythonhosted.org/packages/06/f8/e3080252773a306d30030b27112c242d18750115dbf36bcb17402754ac02/pendulum-0.5.2-cp35-cp35m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "9b7103c412eb6fd0ffafabba9b5d7002",
+ "sha256": "79835aac1824dc42d896d5b3b95370cf969cb0952c1196418c3ad3fe9f51d2a6"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.5.2.tar.gz",
+ "has_sig": false,
+ "md5_digest": "9b7103c412eb6fd0ffafabba9b5d7002",
+ "packagetype": "sdist",
+ "python_version": "source",
+ "requires_python": null,
+ "size": 71055,
+ "upload_time": "2016-08-22T16:29:28",
+ "url": "https://files.pythonhosted.org/packages/fa/9b/4e74ac0e2a6d894802cf388cf4af64f4184ff8d6950ad31ced41a72ec5d1/pendulum-0.5.2.tar.gz"
+ }
+ ],
+ "0.5.3": [
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "6d0dde7ef64e22bfec6f74fa6a918c75",
+ "sha256": "93f8c43e121edbb5edef0815a07d05fd2577b0a6045a8c991381bb5278d25743"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.5.3-cp27-cp27m-macosx_10_11_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "6d0dde7ef64e22bfec6f74fa6a918c75",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": null,
+ "size": 110363,
+ "upload_time": "2016-08-29T17:26:24",
+ "url": "https://files.pythonhosted.org/packages/77/44/d35698f1029fea2e9347059948b26647ea43e6d2616650ea351c45711c23/pendulum-0.5.3-cp27-cp27m-macosx_10_11_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "43971de190b2ad242fcc4b50436afa23",
+ "sha256": "a41ddcf3829c04fd0f3a8a965d6c121d2470e49f60dcbfd3a85e02fbfd213184"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.5.3-cp27-cp27m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "43971de190b2ad242fcc4b50436afa23",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": null,
+ "size": 143331,
+ "upload_time": "2016-08-29T17:24:48",
+ "url": "https://files.pythonhosted.org/packages/1c/42/bc7a49bd89bc4d746623af8bc33411d65a3f4a07a6a3882f23dcc06f7941/pendulum-0.5.3-cp27-cp27m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "8790a56550558c52f0247dde177a1e7e",
+ "sha256": "bd50f1c7d7a41ad01de37de7a8e0dad002b709e2c104cc4cf88a7ebd654cfa52"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.5.3-cp27-cp27m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "8790a56550558c52f0247dde177a1e7e",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": null,
+ "size": 146715,
+ "upload_time": "2016-08-29T17:18:15",
+ "url": "https://files.pythonhosted.org/packages/e8/06/4bfb51d8a24a2185664476fb622022de08bc12b89a59b8312b9a652665e0/pendulum-0.5.3-cp27-cp27m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "fb61279dc9c2e2fb86f16595010c1cb8",
+ "sha256": "ca007fda0e4ee176ceda4a2b53f37440b495ecdf3e206854098e938a187246b7"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.5.3-cp35-cp35m-macosx_10_11_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "fb61279dc9c2e2fb86f16595010c1cb8",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": null,
+ "size": 110471,
+ "upload_time": "2016-08-29T17:26:37",
+ "url": "https://files.pythonhosted.org/packages/0a/0d/9b3fb18e788d6dcb6672780798595832c022150ef47ccbbfdc6f0127ecca/pendulum-0.5.3-cp35-cp35m-macosx_10_11_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "efba9191039e745f6765c812ed1f654d",
+ "sha256": "8191414f06d9082982cad4e31f5d5b5e2cf8cb09e2796d428e230db9d40332c2"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.5.3-cp35-cp35m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "efba9191039e745f6765c812ed1f654d",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": null,
+ "size": 146512,
+ "upload_time": "2016-08-29T17:24:52",
+ "url": "https://files.pythonhosted.org/packages/23/36/3c2e3fcb7a99240a749dee8b6fa775055cc2676bb2ec328258797f91f553/pendulum-0.5.3-cp35-cp35m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "677d556566fb47dba529c9cb90096dd3",
+ "sha256": "1e86814d6dbfc19866effe3707632556e93bae29b8bbfca25ec32ea7761a0e9a"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.5.3-cp35-cp35m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "677d556566fb47dba529c9cb90096dd3",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": null,
+ "size": 148755,
+ "upload_time": "2016-08-29T17:18:19",
+ "url": "https://files.pythonhosted.org/packages/53/dc/ac9c228f4a4d5615cd91293d2b3ae925c15b8d4bf9468d2f0c756baf6ff7/pendulum-0.5.3-cp35-cp35m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "490244596edb10f21cfba8f13e82812e",
+ "sha256": "e2c746aef0887e988624ce79364ece6432376eabf5e4761eaceeb5ee81bd9011"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.5.3.tar.gz",
+ "has_sig": false,
+ "md5_digest": "490244596edb10f21cfba8f13e82812e",
+ "packagetype": "sdist",
+ "python_version": "source",
+ "requires_python": null,
+ "size": 70600,
+ "upload_time": "2016-08-29T17:11:25",
+ "url": "https://files.pythonhosted.org/packages/73/07/d6a38fde08cab36aff11a1e8cfe4e85b44c27d7e86a3d3aff18cd34af10e/pendulum-0.5.3.tar.gz"
+ }
+ ],
+ "0.5.4": [
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "54fa4ff719aaf0a6387227de94d5f868",
+ "sha256": "cc2700914651f259aaeb0291f50ead55f7b836d92301078ce476e62208a543b6"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.5.4-cp27-cp27m-macosx_10_11_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "54fa4ff719aaf0a6387227de94d5f868",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": null,
+ "size": 110967,
+ "upload_time": "2016-08-30T05:40:06",
+ "url": "https://files.pythonhosted.org/packages/03/85/dfbd62357b06c775b2eab463a2687a343b7fa26c1f5b20359750a76a9f43/pendulum-0.5.4-cp27-cp27m-macosx_10_11_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "e01ff6ad949fdf7cba8e0d3e2fc55d20",
+ "sha256": "63ec56caf14ad11794d5b49c08c508f2c34248a598661858d714d01b4b95307a"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.5.4-cp27-cp27m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "e01ff6ad949fdf7cba8e0d3e2fc55d20",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": null,
+ "size": 143867,
+ "upload_time": "2016-08-30T05:52:26",
+ "url": "https://files.pythonhosted.org/packages/29/0e/e8dd9b02e8a95b5bdb52a083c9a44f06ab9bd2b90ada588a8c34b01a2f6e/pendulum-0.5.4-cp27-cp27m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "39a757904de406d6ddacb4aefaa8de28",
+ "sha256": "de848c17a2cceae47a30cc40e1a4b5db4751e1e74f7bd1b77669d002b22e7e32"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.5.4-cp27-cp27m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "39a757904de406d6ddacb4aefaa8de28",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": null,
+ "size": 147252,
+ "upload_time": "2016-08-30T05:49:21",
+ "url": "https://files.pythonhosted.org/packages/bd/ca/af8a623862b1961b446abaa516e71019c86fa592dc1fc8ecdbdc1f34c9e0/pendulum-0.5.4-cp27-cp27m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "51aafa0eb0b35bb44d621cc3069e5591",
+ "sha256": "d21c6622d374b703752f134428d6cde89810846e5a6af5669f654c19ecfe80d4"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.5.4-cp35-cp35m-macosx_10_11_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "51aafa0eb0b35bb44d621cc3069e5591",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": null,
+ "size": 111071,
+ "upload_time": "2016-08-30T05:40:19",
+ "url": "https://files.pythonhosted.org/packages/3d/44/69e119d4dcbc139b31105eeed3bab7cd71c88e965ffa2f56c2f43f87de69/pendulum-0.5.4-cp35-cp35m-macosx_10_11_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "745bd66eea00aee326ff592a28494688",
+ "sha256": "cac90c28fc355e71d8c6b836719d652ba673c8b76f4fd9a596aaab1094a61a6f"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.5.4-cp35-cp35m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "745bd66eea00aee326ff592a28494688",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": null,
+ "size": 147074,
+ "upload_time": "2016-08-30T05:52:30",
+ "url": "https://files.pythonhosted.org/packages/cf/05/ba7bf113462caec4907370b33017f07b35d7c6f56bf95d34c08e915c0ee2/pendulum-0.5.4-cp35-cp35m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "bbbfe9d581589edffb5403830b5c3c41",
+ "sha256": "b5c8c0aa1be784dd5637bf9feceee4cbf76f8129318c84faf8161c04bd3cc50d"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.5.4-cp35-cp35m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "bbbfe9d581589edffb5403830b5c3c41",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": null,
+ "size": 149289,
+ "upload_time": "2016-08-30T05:49:26",
+ "url": "https://files.pythonhosted.org/packages/61/8b/c40c4f0d3abcc8cf4c2ad37210c0cf55f126496d897d568e4f73b83ffc1e/pendulum-0.5.4-cp35-cp35m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "8dfc8afcb592569e38d51adfbe087106",
+ "sha256": "0d04aad07c8e2148f6e8903a2785d85a2006f12f574f7bc1649b4bb331c8b1ac"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.5.4.tar.gz",
+ "has_sig": false,
+ "md5_digest": "8dfc8afcb592569e38d51adfbe087106",
+ "packagetype": "sdist",
+ "python_version": "source",
+ "requires_python": null,
+ "size": 70815,
+ "upload_time": "2016-08-30T05:38:32",
+ "url": "https://files.pythonhosted.org/packages/ef/b6/e785a87be64f26b190beee6d83b9cb619bc2de848dc05d590d494c0c52c9/pendulum-0.5.4.tar.gz"
+ }
+ ],
+ "0.5.5": [
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "ef6cb4edcf2f102a1cd5f61c43a2e201",
+ "sha256": "929144c0d97d692ced3243cc34e6b5bd19f1a4da22b700d822e56b05b892b656"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.5.5-cp27-cp27m-macosx_10_11_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "ef6cb4edcf2f102a1cd5f61c43a2e201",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": null,
+ "size": 111023,
+ "upload_time": "2016-09-01T15:38:58",
+ "url": "https://files.pythonhosted.org/packages/1f/d2/f16ccdc50a7a41e965b40edc0d7565889e64d4143642cc38b31e2bc15405/pendulum-0.5.5-cp27-cp27m-macosx_10_11_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "7cf5fb837dbc71bc9554b260985dee1e",
+ "sha256": "564f059617d65d119bffc835f551cfcf8a3ec80c7288bb2cfab7905e2d059dc4"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.5.5-cp27-cp27m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "7cf5fb837dbc71bc9554b260985dee1e",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": null,
+ "size": 143927,
+ "upload_time": "2016-09-01T15:37:32",
+ "url": "https://files.pythonhosted.org/packages/09/68/595fd036ca93d9e794b57beadd54b2df93fa5223c904a1f3302fb3b851c7/pendulum-0.5.5-cp27-cp27m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "444828de9fc0ebc3e87d4e57e06c1a17",
+ "sha256": "e1affb6193e30c1e9fe4d9739ce54268ae5accdb80a2652b576452e212d14f72"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.5.5-cp27-cp27m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "444828de9fc0ebc3e87d4e57e06c1a17",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": null,
+ "size": 147315,
+ "upload_time": "2016-09-01T15:34:57",
+ "url": "https://files.pythonhosted.org/packages/28/22/4b0f2cb3cc3dafb7e6d3fb8b1c7a052a81bc2b8e098c1d786a5ebf2384ef/pendulum-0.5.5-cp27-cp27m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "1cf2bf44d42fa44ec9df9c8b9dbf931d",
+ "sha256": "56ceeb870037ceb1e31c32cc25ba1adbcd92c1552ef17af1b06ff47d438329b8"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.5.5-cp35-cp35m-macosx_10_11_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "1cf2bf44d42fa44ec9df9c8b9dbf931d",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": null,
+ "size": 111133,
+ "upload_time": "2016-09-01T15:38:45",
+ "url": "https://files.pythonhosted.org/packages/65/c4/6e9147c38a14b0c21469b6e89a759240530696595cd6e0c978106ffa3546/pendulum-0.5.5-cp35-cp35m-macosx_10_11_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "1235080e8e9a3169765e19fbed0c9f83",
+ "sha256": "1f5a7ade5f144ca7864bf0082bea17cbbb82cfe9e1e3845f610f4b1f20e16fd9"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.5.5-cp35-cp35m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "1235080e8e9a3169765e19fbed0c9f83",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": null,
+ "size": 147136,
+ "upload_time": "2016-09-01T15:37:36",
+ "url": "https://files.pythonhosted.org/packages/88/b1/41292303cb858aa43e0b9b1402a0b53e56f008cdd1d26e36acba80703ce5/pendulum-0.5.5-cp35-cp35m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "3a4ee340161deb980d7801a280a0f474",
+ "sha256": "84a431da2cda1f5b34fbbdfe2ba4d4ac920203d952e4c95e208cd51b7091a4eb"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.5.5-cp35-cp35m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "3a4ee340161deb980d7801a280a0f474",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": null,
+ "size": 149357,
+ "upload_time": "2016-09-01T15:35:02",
+ "url": "https://files.pythonhosted.org/packages/81/df/b634ccf92e16627333aef76048a9bf31caac089eb61510c3a8025ee14942/pendulum-0.5.5-cp35-cp35m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "95eebe3720244726dda8431280282241",
+ "sha256": "5082144ee8c9bba9040a235ed58810a3d09a08f2ad80edc838b695a6a3629e9f"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.5.5.tar.gz",
+ "has_sig": false,
+ "md5_digest": "95eebe3720244726dda8431280282241",
+ "packagetype": "sdist",
+ "python_version": "source",
+ "requires_python": null,
+ "size": 70894,
+ "upload_time": "2016-09-01T15:32:34",
+ "url": "https://files.pythonhosted.org/packages/49/4c/f7c778715993d0257956a73abc02d5956b79b02e3078ee2b0aba15020579/pendulum-0.5.5.tar.gz"
+ }
+ ],
+ "0.6.0": [
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "0caa0c78d154f721e3d06abd92c3752c",
+ "sha256": "39ea8c707df3806d14194462da2d0c6acd54057fc46649de8486e082c4f55986"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.6.0-cp27-cp27m-macosx_10_11_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "0caa0c78d154f721e3d06abd92c3752c",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": null,
+ "size": 83631,
+ "upload_time": "2016-09-12T17:01:26",
+ "url": "https://files.pythonhosted.org/packages/20/45/cc998aa3fb5f4eec53be4ad773b8665fa6e7eda6f1511f3150d1d8ddd8ed/pendulum-0.6.0-cp27-cp27m-macosx_10_11_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "778b9ae47406cf8698e5d0613ef7832a",
+ "sha256": "6a1b8ed3910c1fe64b900b3227e31763841c7a83726acbecc3356927a1c1f3e9"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.6.0-cp27-cp27m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "778b9ae47406cf8698e5d0613ef7832a",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": null,
+ "size": 91978,
+ "upload_time": "2016-09-12T16:59:56",
+ "url": "https://files.pythonhosted.org/packages/62/a9/b9fe2b5994ceb452430f200a03f69f2315f4954ae6678026d440721726e0/pendulum-0.6.0-cp27-cp27m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "43a6314a5a6b16d8b026e7c5ff9f73bb",
+ "sha256": "e1961409545efadf1c506138f19058375bd8a2a7a1a3e439b9b5a49b2d71c2ff"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.6.0-cp27-cp27m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "43a6314a5a6b16d8b026e7c5ff9f73bb",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": null,
+ "size": 91317,
+ "upload_time": "2016-09-12T16:57:37",
+ "url": "https://files.pythonhosted.org/packages/08/42/a598bc5ce3265eb9b71a100a8b1afbc771c7ffeacae0faee353bcc048093/pendulum-0.6.0-cp27-cp27m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "a97db3bd956309899691081cb1d219da",
+ "sha256": "02f34be3274885c78f985a26710b3cf5ed0323028543b05b570d5ae4a2434bd6"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.6.0-cp35-cp35m-macosx_10_11_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "a97db3bd956309899691081cb1d219da",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": null,
+ "size": 83722,
+ "upload_time": "2016-09-12T17:01:13",
+ "url": "https://files.pythonhosted.org/packages/95/16/a630a27606ae53ef93be3e3a3086d60e7f1ef73c0114f63886980fe81aaf/pendulum-0.6.0-cp35-cp35m-macosx_10_11_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "5628ae00425864cec4edb448f9796263",
+ "sha256": "cc3c7a771f124218b21923b33d10e23da5697eae80a4ef3c81a17c2f50fe5236"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.6.0-cp35-cp35m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "5628ae00425864cec4edb448f9796263",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": null,
+ "size": 92161,
+ "upload_time": "2016-09-12T17:00:00",
+ "url": "https://files.pythonhosted.org/packages/73/1b/3d46e8c1ba605e6cc7a2bee68d78a2e9ed4337b4fdc66c293f30b21b50ac/pendulum-0.6.0-cp35-cp35m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "707ea4e18491c98694d13051c8972ed5",
+ "sha256": "7ceaf4e681f2e9a4cee7dad540ad4bdf435b696731033a7032536f593364eb18"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.6.0-cp35-cp35m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "707ea4e18491c98694d13051c8972ed5",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": null,
+ "size": 91459,
+ "upload_time": "2016-09-12T16:57:41",
+ "url": "https://files.pythonhosted.org/packages/70/22/8aedc1663cb14b94fd3047d33505da69b5229971c5033735847d7579fe08/pendulum-0.6.0-cp35-cp35m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "bb86cf3771042eb431fcb83a6cfc080b",
+ "sha256": "17d91aa45afe53793ac28ccd05ae10086c9ffb22e91703b2b0cdf65b32848340"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.6.0.tar.gz",
+ "has_sig": false,
+ "md5_digest": "bb86cf3771042eb431fcb83a6cfc080b",
+ "packagetype": "sdist",
+ "python_version": "source",
+ "requires_python": null,
+ "size": 50391,
+ "upload_time": "2016-09-12T16:55:01",
+ "url": "https://files.pythonhosted.org/packages/42/6f/c421e071126574375f4b2ceabea1296fe1a09fe8dd9a450e5c81c2bf3b96/pendulum-0.6.0.tar.gz"
+ }
+ ],
+ "0.6.1": [
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "cc039a34d440b39696fd26dc7d30fd5b",
+ "sha256": "5a1ef8bf74a9409e8c31ab900b3d781a953d1c963a243c3bea88c8fc6fcd76a2"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.6.1-cp27-cp27m-macosx_10_11_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "cc039a34d440b39696fd26dc7d30fd5b",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": null,
+ "size": 83388,
+ "upload_time": "2016-09-19T17:49:37",
+ "url": "https://files.pythonhosted.org/packages/fe/4b/0cd8376ef9fad7d7251dd3294f2422b8025b5a7e61c9f33584a409c7b8f4/pendulum-0.6.1-cp27-cp27m-macosx_10_11_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "85d0b1441f335e8a644a5b3dfbef07c7",
+ "sha256": "120072a924cdc6d9c37b7890837da8813a560656f49a2de71f693c30cf4ee0d8"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.6.1-cp27-cp27m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "85d0b1441f335e8a644a5b3dfbef07c7",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": null,
+ "size": 91740,
+ "upload_time": "2016-09-19T17:48:26",
+ "url": "https://files.pythonhosted.org/packages/e4/7a/e706df0644d1536f690ea4525814dfe9f35f6431a1be01574440b4fbf2b7/pendulum-0.6.1-cp27-cp27m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "0019fe6b506ead44a66eaf1bda8fce6d",
+ "sha256": "d8f52e343604ebe729e6e8f3ac36172efe27dde4f239283f16eef353727b3691"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.6.1-cp27-cp27m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "0019fe6b506ead44a66eaf1bda8fce6d",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": null,
+ "size": 91081,
+ "upload_time": "2016-09-19T17:45:32",
+ "url": "https://files.pythonhosted.org/packages/05/e8/e9aec8e214705033b1d49abe8ad2076e7641d8c3abbafa8dea3478e3f56d/pendulum-0.6.1-cp27-cp27m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "de16e1d88c10e86fbcd1740bb6b80196",
+ "sha256": "500271c27102f71a6f0080766c38fa223ebefeff5f78cc9a0f39f7fba179105d"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.6.1-cp35-cp35m-macosx_10_11_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "de16e1d88c10e86fbcd1740bb6b80196",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": null,
+ "size": 83479,
+ "upload_time": "2016-09-19T17:49:52",
+ "url": "https://files.pythonhosted.org/packages/09/ac/17fdb73480be1a9463bf339c11c52f2ba111ddb0c1b555df609166df4b4b/pendulum-0.6.1-cp35-cp35m-macosx_10_11_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "b96788e1f68f9ae841ae531c0e9493f5",
+ "sha256": "d78905e7ca59897b247380c154cb3b79e0ceb31f53f3e649e782f3346464efb6"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.6.1-cp35-cp35m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "b96788e1f68f9ae841ae531c0e9493f5",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": null,
+ "size": 91919,
+ "upload_time": "2016-09-19T17:48:30",
+ "url": "https://files.pythonhosted.org/packages/f1/51/1d90f25b82011ca8c2148020ba9ce67a021ed81d57839ee5ded96efbf0db/pendulum-0.6.1-cp35-cp35m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "1b518c922f90f0de3b92fa9f849dc40f",
+ "sha256": "7c8721db252c87a1ab787586626d95bd8caea268de01a53c44865f24610c83d1"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.6.1-cp35-cp35m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "1b518c922f90f0de3b92fa9f849dc40f",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": null,
+ "size": 91217,
+ "upload_time": "2016-09-19T17:45:36",
+ "url": "https://files.pythonhosted.org/packages/3f/d5/8ab96ad7e3d1022d713d7cfd25023c6cf6d486c3a3ea69016d3b61b7e561/pendulum-0.6.1-cp35-cp35m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "2362d866eae0adc6527a8d54315d09f0",
+ "sha256": "42275f7416e970dea218c9de7b56384ddf1de2cd950a3ad0932d0ba3cfc4af91"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.6.1.tar.gz",
+ "has_sig": false,
+ "md5_digest": "2362d866eae0adc6527a8d54315d09f0",
+ "packagetype": "sdist",
+ "python_version": "source",
+ "requires_python": null,
+ "size": 50187,
+ "upload_time": "2016-09-19T17:41:15",
+ "url": "https://files.pythonhosted.org/packages/60/37/44c6ff4fa1e8c0b23b23775100269227070f835d46e165dcdffbf6db02fe/pendulum-0.6.1.tar.gz"
+ }
+ ],
+ "0.6.2": [
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "7c65d9a236ef1d516c39fba9533b844e",
+ "sha256": "4c0edf7eeaef3ae107362e64343dbbc20f910baa16b0281520e4e1878f3e462a"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.6.2-cp27-cp27m-macosx_10_11_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "7c65d9a236ef1d516c39fba9533b844e",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": null,
+ "size": 83462,
+ "upload_time": "2016-09-26T22:36:57",
+ "url": "https://files.pythonhosted.org/packages/68/a1/af97ebc461661114ca61897741cb08b182ad039a1a4193f86a1ac4132550/pendulum-0.6.2-cp27-cp27m-macosx_10_11_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "d93d803fe421e758a09859616b9067eb",
+ "sha256": "d2b537e392bb33937deaebf1c3583ee4eb7ed39df619cadbe1b4a65b072168ba"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.6.2-cp27-cp27m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "d93d803fe421e758a09859616b9067eb",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": null,
+ "size": 91810,
+ "upload_time": "2016-09-26T22:35:03",
+ "url": "https://files.pythonhosted.org/packages/13/f0/749c61d520864a7ae8f600ba7bf992fe2587b780a516658f6710cbaa5368/pendulum-0.6.2-cp27-cp27m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "791ec5f1abae71dfaaa5cc499844610f",
+ "sha256": "7c7e11f3b8a7d10b8f3c1bc402ed0ef52e05712dc09e323e5c1aa503967be2fa"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.6.2-cp27-cp27m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "791ec5f1abae71dfaaa5cc499844610f",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": null,
+ "size": 91149,
+ "upload_time": "2016-09-26T22:32:10",
+ "url": "https://files.pythonhosted.org/packages/1c/80/d18e5d00dd72678e1004213fb1b94faaba462d6e2ede03def76c92c08b06/pendulum-0.6.2-cp27-cp27m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "ae337cf1c4ddeffb4385be7339f21f7b",
+ "sha256": "cdccb5ee1045eae52d58b47015414f8771211ab2fb5f7f37f740a444ccfd3403"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.6.2-cp35-cp35m-macosx_10_11_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "ae337cf1c4ddeffb4385be7339f21f7b",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": null,
+ "size": 83551,
+ "upload_time": "2016-09-26T22:36:45",
+ "url": "https://files.pythonhosted.org/packages/35/25/ef400ec28e72d02efd341f0d6b6b608fe2483e6d79630afaea98f6b24ec4/pendulum-0.6.2-cp35-cp35m-macosx_10_11_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "9ce261ae74882d9b0aadf13e61823006",
+ "sha256": "e86c341c0beffa8d487d323267c27bafbe1367ede81d321a8809876a0c9208d9"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.6.2-cp35-cp35m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "9ce261ae74882d9b0aadf13e61823006",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": null,
+ "size": 91988,
+ "upload_time": "2016-09-26T22:35:07",
+ "url": "https://files.pythonhosted.org/packages/83/2f/ac4952c5bf3a55c9c2c798baa79b1cc7c9eb2ec15630fa49c69a2fc01aba/pendulum-0.6.2-cp35-cp35m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "4bd6e701421a33e8b9b6187c48a70575",
+ "sha256": "9c7569721fa322a4fe2c49ddadddb728ca2b86289fd5bfa7975c9d58d983f670"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.6.2-cp35-cp35m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "4bd6e701421a33e8b9b6187c48a70575",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": null,
+ "size": 91298,
+ "upload_time": "2016-09-26T22:32:14",
+ "url": "https://files.pythonhosted.org/packages/dd/6a/88f5ee069eeecaa14b3abe6ee58c9f8794104bc02071986638b0866904de/pendulum-0.6.2-cp35-cp35m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "6a0f857a0b9c34160a848871d269f25e",
+ "sha256": "b5a33524c954b0c99b88422d7a58bfa0405616d9f11882749cd2b6a700e139a6"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.6.2.tar.gz",
+ "has_sig": false,
+ "md5_digest": "6a0f857a0b9c34160a848871d269f25e",
+ "packagetype": "sdist",
+ "python_version": "source",
+ "requires_python": null,
+ "size": 50274,
+ "upload_time": "2016-09-26T22:27:54",
+ "url": "https://files.pythonhosted.org/packages/29/76/44fb90c50921211eced8dfbfe33972ba941c626fa959fabe879a557098df/pendulum-0.6.2.tar.gz"
+ }
+ ],
+ "0.6.3": [
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "8eecb558c2751db8c74ade037e0db495",
+ "sha256": "ba25009e6302a637621307fc53792603f4f137fd61f4eb3d4395510776481540"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.6.3-cp27-cp27m-macosx_10_11_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "8eecb558c2751db8c74ade037e0db495",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": null,
+ "size": 83567,
+ "upload_time": "2016-10-19T22:11:51",
+ "url": "https://files.pythonhosted.org/packages/0f/19/ad611281e4eccde93f70ffb48f322c65e890d23e4d873668b22e355f8f3d/pendulum-0.6.3-cp27-cp27m-macosx_10_11_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "5db5aded24b2f04ba8ff486d5b1f4600",
+ "sha256": "7d06d11557ce4204cc16f95a14ca734c3665c7f76470ac3e1511ceb1353ef0c1"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.6.3-cp27-cp27m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "5db5aded24b2f04ba8ff486d5b1f4600",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": null,
+ "size": 91919,
+ "upload_time": "2016-10-19T22:09:57",
+ "url": "https://files.pythonhosted.org/packages/0b/b8/08e312b95b9ed060224259b0839791a2c778bd58318380fa23a54fec6b3f/pendulum-0.6.3-cp27-cp27m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "04ef915161e981ff7a9548c1ee029bc9",
+ "sha256": "68c70080095c5a438c8a30d921fbd1e875ad6478ea3e33e089e6579a3a86d5a1"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.6.3-cp27-cp27m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "04ef915161e981ff7a9548c1ee029bc9",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": null,
+ "size": 91253,
+ "upload_time": "2016-10-19T22:03:45",
+ "url": "https://files.pythonhosted.org/packages/7e/78/6061fe45d33bec32dc7b6c4be5fd4ad16a9450d493f835f54467c9f220f3/pendulum-0.6.3-cp27-cp27m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "8aae45bb83c3dd87a3941ef5bee5f75f",
+ "sha256": "ddf8aefe8996cfa299d8f58825029e4a7754312b12e0f846b43adb5eef30eee9"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.6.3-cp35-cp35m-macosx_10_11_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "8aae45bb83c3dd87a3941ef5bee5f75f",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": null,
+ "size": 83654,
+ "upload_time": "2016-10-19T22:12:05",
+ "url": "https://files.pythonhosted.org/packages/39/0e/43c2b49e51c9ca25f1bc7860e3814ba9eee632023b8a9106e031b6dce06b/pendulum-0.6.3-cp35-cp35m-macosx_10_11_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "d3bf591ee850441f8eb115f96f43d0b3",
+ "sha256": "4750b418eac8704858d172ade547b1827447e0997b8f445277f17201634a2e01"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.6.3-cp35-cp35m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "d3bf591ee850441f8eb115f96f43d0b3",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": null,
+ "size": 92095,
+ "upload_time": "2016-10-19T22:10:01",
+ "url": "https://files.pythonhosted.org/packages/4d/6f/be61d8f3a72d47b48e14a136b8c58077afb431c90857d4b6eea791984b19/pendulum-0.6.3-cp35-cp35m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "5901ece4d796a736564f0f248430162f",
+ "sha256": "5917e8462f2d8e79d9ecb481a0a18e200e088b706e88f5695e11da872ef539d9"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.6.3-cp35-cp35m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "5901ece4d796a736564f0f248430162f",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": null,
+ "size": 91397,
+ "upload_time": "2016-10-19T22:03:50",
+ "url": "https://files.pythonhosted.org/packages/9b/f6/7d70d3f30a7630321aceaeefb64e8d8faace5524ae14123ada71da03d123/pendulum-0.6.3-cp35-cp35m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "eecd76a582bbbb1ac9ffa3a9afa19a49",
+ "sha256": "982f18306324cd5444dda07221b5be78e04a31b4ca72cffe091be124950c9ff3"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.6.3.tar.gz",
+ "has_sig": false,
+ "md5_digest": "eecd76a582bbbb1ac9ffa3a9afa19a49",
+ "packagetype": "sdist",
+ "python_version": "source",
+ "requires_python": null,
+ "size": 50357,
+ "upload_time": "2016-10-19T21:57:07",
+ "url": "https://files.pythonhosted.org/packages/3a/dd/f0c46ec9f91d3a445ef208460a4ee7de203238e87cd085464a0ac5de30c2/pendulum-0.6.3.tar.gz"
+ }
+ ],
+ "0.6.4": [
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "672f36e869681291964041d569d49472",
+ "sha256": "867c504d3c2cfddca4076fec7e8d13a88d5ee0177cc61519b246ac4ed7c7a109"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.6.4-cp27-cp27m-macosx_10_11_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "672f36e869681291964041d569d49472",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": null,
+ "size": 83735,
+ "upload_time": "2016-10-23T00:05:04",
+ "url": "https://files.pythonhosted.org/packages/72/38/d0e1056ca99c75b07f0f02813e8746558da07176c79cbe7d6d7b0e1e1e39/pendulum-0.6.4-cp27-cp27m-macosx_10_11_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "8c31f0043501c793382d840adc0c2a5b",
+ "sha256": "8480c2143b0fe4ab816aca2967b133c2bb04bd83afa66aecc0c58997267258cc"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.6.4-cp27-cp27m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "8c31f0043501c793382d840adc0c2a5b",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": null,
+ "size": 92078,
+ "upload_time": "2016-10-23T00:03:49",
+ "url": "https://files.pythonhosted.org/packages/62/23/6bdb0d653ef85301a555528fdf2a04ce918b395f46962f9f0a91ef1d09fa/pendulum-0.6.4-cp27-cp27m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "4e88aec7b92d2fd7a10322c38424e553",
+ "sha256": "afce8f5d607432301f44ea72f80748e683656b49d697d8a02ea2b9bba93d1aa4"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.6.4-cp27-cp27m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "4e88aec7b92d2fd7a10322c38424e553",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": null,
+ "size": 91422,
+ "upload_time": "2016-10-22T23:58:45",
+ "url": "https://files.pythonhosted.org/packages/92/83/d38cb6131fdbb373ee863991cf13f8c989826e39b7e110f02e38dc52b25d/pendulum-0.6.4-cp27-cp27m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "ef078d1645d2397464d780e6953c351a",
+ "sha256": "c8e46661da2b72276f9b3445f08fbfa6af809251a7dfaf8b4bee4225abacb6eb"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.6.4-cp35-cp35m-macosx_10_11_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "ef078d1645d2397464d780e6953c351a",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": null,
+ "size": 83825,
+ "upload_time": "2016-10-23T00:04:51",
+ "url": "https://files.pythonhosted.org/packages/8b/6a/e82611d363d148dce932003bb048448e5d727b4ccd3d340ef92a548925ab/pendulum-0.6.4-cp35-cp35m-macosx_10_11_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "7b3198eedba349813a5e25e643c0a58f",
+ "sha256": "2259805d001683a9ac135a72f9e1fce51b6866ce9f956efc2aced9cd7bd47b31"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.6.4-cp35-cp35m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "7b3198eedba349813a5e25e643c0a58f",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": null,
+ "size": 92263,
+ "upload_time": "2016-10-23T00:03:53",
+ "url": "https://files.pythonhosted.org/packages/82/3b/fcc3e3a2ab260030b7b48a12dff6d205422b17143c6cfafe78f2d897bc38/pendulum-0.6.4-cp35-cp35m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "5e28a0765427b7bce803d144a1b496de",
+ "sha256": "7871aca136a28caaeed43ed4cac1866996567bd82b040e78920bae2c4c3080fa"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.6.4-cp35-cp35m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "5e28a0765427b7bce803d144a1b496de",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": null,
+ "size": 91564,
+ "upload_time": "2016-10-22T23:58:49",
+ "url": "https://files.pythonhosted.org/packages/af/a8/c9def35160a4e1a68c3eea65e2ed8287f8aacda24bf75fd93d0c5d9871c4/pendulum-0.6.4-cp35-cp35m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "17d5790d6bc07265ad9d144b0cf21f38",
+ "sha256": "8f08311a48aef4ef1427e0c6ee5278befb9d0a17a1085ff5ecdd380ed3922744"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.6.4.tar.gz",
+ "has_sig": false,
+ "md5_digest": "17d5790d6bc07265ad9d144b0cf21f38",
+ "packagetype": "sdist",
+ "python_version": "source",
+ "requires_python": null,
+ "size": 50524,
+ "upload_time": "2016-10-22T23:55:13",
+ "url": "https://files.pythonhosted.org/packages/d4/a1/a2f5b2c22386a1b652442548890a442d8669749eddb5402e4048228c4a5c/pendulum-0.6.4.tar.gz"
+ }
+ ],
+ "0.6.5": [
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "b0186bb0a48edf42ca94123a67a22963",
+ "sha256": "a096372de09ceced54d804b5ccf4b44b8dcf8c407106d27287602185974c5d9a"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.6.5-cp27-cp27m-macosx_10_11_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "b0186bb0a48edf42ca94123a67a22963",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": null,
+ "size": 83852,
+ "upload_time": "2016-10-31T18:06:39",
+ "url": "https://files.pythonhosted.org/packages/6b/7d/f9d79e25cb62a8341d3ef8cf22274b460a88f990fc40fddfacb72cce369e/pendulum-0.6.5-cp27-cp27m-macosx_10_11_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "0dcfc4492b0ba96fd72b4bd1c8fdfeb1",
+ "sha256": "3dcf3c33078fd3d451bf45e46956daf7401e39a9dff1f1f5b57e2545eb8247b9"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.6.5-cp27-cp27m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "0dcfc4492b0ba96fd72b4bd1c8fdfeb1",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": null,
+ "size": 92199,
+ "upload_time": "2016-10-31T18:05:32",
+ "url": "https://files.pythonhosted.org/packages/97/b9/467cb9520497ec3f65b163cc4d729ebd5a5f83d09ef39c7c26afeb3c49df/pendulum-0.6.5-cp27-cp27m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "3071c88120c07193e6e8c82644a6805f",
+ "sha256": "93b05c8939a6a0ea875c7670e269b6b91fd56983581af75a7384cc89e8b1b03b"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.6.5-cp27-cp27m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "3071c88120c07193e6e8c82644a6805f",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": null,
+ "size": 91540,
+ "upload_time": "2016-10-31T17:57:34",
+ "url": "https://files.pythonhosted.org/packages/92/e8/979c4015caba12ed9a24f02fa747fb5738f06ca13b450e1c89f44a714652/pendulum-0.6.5-cp27-cp27m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "c9358ae483f18052836d60034c3cb6f3",
+ "sha256": "bfdb29e475dbf1610815d0479ef380f8ba9523fc63f69c003e02d840441efd8b"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.6.5-cp35-cp35m-macosx_10_11_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "c9358ae483f18052836d60034c3cb6f3",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": null,
+ "size": 83942,
+ "upload_time": "2016-10-31T18:06:52",
+ "url": "https://files.pythonhosted.org/packages/19/08/c3a082a0ec252f1289b921558398c48e816f35aa748f86173d60048a1378/pendulum-0.6.5-cp35-cp35m-macosx_10_11_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "639ff633b634f22a1dec4d250f4bea46",
+ "sha256": "24f2b9fdb30a50274c05f64ea4c942e9f54b12d4ebb210549000ac3161888557"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.6.5-cp35-cp35m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "639ff633b634f22a1dec4d250f4bea46",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": null,
+ "size": 92377,
+ "upload_time": "2016-10-31T18:04:11",
+ "url": "https://files.pythonhosted.org/packages/8b/e0/b65ffbbca6a3f8e3557dce0300ff31b33dfb65df43c90165bbefdfd33a1f/pendulum-0.6.5-cp35-cp35m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "e39e357423fcc8a2e5bdc515c97aeb4c",
+ "sha256": "7302a43570fa2c368dabfbe6a8208fe5a0b7a0db180a23c285eee47b229680da"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.6.5-cp35-cp35m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "e39e357423fcc8a2e5bdc515c97aeb4c",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": null,
+ "size": 91684,
+ "upload_time": "2016-10-31T17:57:39",
+ "url": "https://files.pythonhosted.org/packages/2b/aa/42c538deb69ca776683e6450c2a2623273d1ad1a886a4a9c1e0fa5cd5907/pendulum-0.6.5-cp35-cp35m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "ca679df9b08b18a1b4f345fdbbc6b72c",
+ "sha256": "46fae28a9d848cf87e5775d5a65bbb30e7967a41988d2288dbd1c694b2d53b71"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.6.5.tar.gz",
+ "has_sig": false,
+ "md5_digest": "ca679df9b08b18a1b4f345fdbbc6b72c",
+ "packagetype": "sdist",
+ "python_version": "source",
+ "requires_python": null,
+ "size": 50805,
+ "upload_time": "2016-10-31T17:48:38",
+ "url": "https://files.pythonhosted.org/packages/3a/5e/d8c90e54aa7cfe2d8b688c87d349d29aa990e0ed49a821c6f19cce48fac4/pendulum-0.6.5.tar.gz"
+ }
+ ],
+ "0.6.6": [
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "cc67a39cf243eaaf11b8e04c768719b8",
+ "sha256": "ad3f4d50dccf2c47fa8f1f8ed0cc4cac568f7c631c58703c07724a84aa39842b"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.6.6-cp27-cp27m-macosx_10_11_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "cc67a39cf243eaaf11b8e04c768719b8",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": null,
+ "size": 83861,
+ "upload_time": "2016-11-25T22:04:07",
+ "url": "https://files.pythonhosted.org/packages/e9/d6/78bd9581d156d18cc23b609a3043214631147c3edd34a70a673f0c3637ab/pendulum-0.6.6-cp27-cp27m-macosx_10_11_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "c724953b3d1e1c4a3a8c6d026065afee",
+ "sha256": "4f8a62cbaeea56f99beccfdb50b6e82461a54477eaa0c72bb6fd68e699b1e583"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.6.6-cp27-cp27m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "c724953b3d1e1c4a3a8c6d026065afee",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": null,
+ "size": 92200,
+ "upload_time": "2016-11-25T22:02:45",
+ "url": "https://files.pythonhosted.org/packages/c0/f9/3c12d6aa0aeb83fd20a4a686b597c017f799f997f97cf494ac9c21f6ed48/pendulum-0.6.6-cp27-cp27m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "0f7ae2263cc235da6d8e7be6c77cb7e1",
+ "sha256": "c53b31359b9205f59afb2289e72a8983d50de1fcbbbb332bf14d518a533d3ba9"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.6.6-cp27-cp27m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "0f7ae2263cc235da6d8e7be6c77cb7e1",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": null,
+ "size": 91542,
+ "upload_time": "2016-11-25T22:01:09",
+ "url": "https://files.pythonhosted.org/packages/9f/21/bc23ccdd59b47af0e818b315f632d40ea90778d087fab127fc583a11907e/pendulum-0.6.6-cp27-cp27m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "c4d3e8cf64684bf22e425a7864b499de",
+ "sha256": "b293584305db262c723446d59b37286be848ee10b31569f5ce2b08c64f2828d3"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.6.6-cp35-cp35m-macosx_10_11_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "c4d3e8cf64684bf22e425a7864b499de",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": null,
+ "size": 83947,
+ "upload_time": "2016-11-25T22:04:19",
+ "url": "https://files.pythonhosted.org/packages/9d/e5/02338e5704c7e7e5d29b9c09cb17b213d974e071d9f7df4bf356732e4a87/pendulum-0.6.6-cp35-cp35m-macosx_10_11_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "eda4b68ec97c589e06a059b0e3083e04",
+ "sha256": "f9553beef2acd91e36dce6df0a2435beb05db258c268066c0ff69da88d21db80"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.6.6-cp35-cp35m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "eda4b68ec97c589e06a059b0e3083e04",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": null,
+ "size": 92379,
+ "upload_time": "2016-11-25T22:02:49",
+ "url": "https://files.pythonhosted.org/packages/7d/94/63318b67e98256ebee3ca36d00e7d943aba0429d4457ee26854dbc37a149/pendulum-0.6.6-cp35-cp35m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "2fcfd6847e9d28ef353a74727824fbba",
+ "sha256": "b77405c52f202c5f70ed5e7b6812bc9c02a508bd3eac731299d979d4e604ce82"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.6.6-cp35-cp35m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "2fcfd6847e9d28ef353a74727824fbba",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": null,
+ "size": 91695,
+ "upload_time": "2016-11-25T22:01:14",
+ "url": "https://files.pythonhosted.org/packages/3d/b9/072ed2eb041d02299e092fd53e5bd610d4bbcd2875c941fd1acb696ef200/pendulum-0.6.6-cp35-cp35m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "977f430b57a34b6d2fe98c8c08bbc703",
+ "sha256": "b8fa6a3ac32d8904234ee07e620c3d6aefd8338c644bf8e053d580936ce6e74d"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.6.6.tar.gz",
+ "has_sig": false,
+ "md5_digest": "977f430b57a34b6d2fe98c8c08bbc703",
+ "packagetype": "sdist",
+ "python_version": "source",
+ "requires_python": null,
+ "size": 50778,
+ "upload_time": "2016-11-25T21:57:46",
+ "url": "https://files.pythonhosted.org/packages/f8/23/cb6facfce303ba6215fe355dad6e9d2a6a027b7e65152c7ca8c0d94247bd/pendulum-0.6.6.tar.gz"
+ }
+ ],
+ "0.7.0": [
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "a5ac9a702b68ca1149742c716140acce",
+ "sha256": "ff5947915fbaa60657f1175866744318dc474a3010b449a2d33a7fa565428d79"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.7.0-cp27-cp27m-macosx_10_11_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "a5ac9a702b68ca1149742c716140acce",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": null,
+ "size": 97666,
+ "upload_time": "2016-12-07T16:50:39",
+ "url": "https://files.pythonhosted.org/packages/49/e6/90165de336ace0f0e696c6cb51f666d6c03e4d39a867902c745103fce72f/pendulum-0.7.0-cp27-cp27m-macosx_10_11_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "cbc0d750fa0b396e12701ff5391387e6",
+ "sha256": "0eeb8f82f21e47feecba00b2a5773614eae170f762d7db5a376134bb0d1bb517"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.7.0-cp27-cp27m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "cbc0d750fa0b396e12701ff5391387e6",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": null,
+ "size": 105952,
+ "upload_time": "2016-12-07T16:50:41",
+ "url": "https://files.pythonhosted.org/packages/40/11/ed1da7f1550501b3fa83d703f747c2fd6817210c555594bd206b00a7a1de/pendulum-0.7.0-cp27-cp27m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "27a17ebc2d1846a9c3316080bc425c8a",
+ "sha256": "c5d178026ec7e43c77a1e2554f511486bf48920c6b938a1c8acede65651e1ec0"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.7.0-cp27-cp27m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "27a17ebc2d1846a9c3316080bc425c8a",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": null,
+ "size": 105335,
+ "upload_time": "2016-12-07T16:50:43",
+ "url": "https://files.pythonhosted.org/packages/1a/33/bf5744a583c4105259aff628610b4dec1cabc445c817822cbe0649999f4d/pendulum-0.7.0-cp27-cp27m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "6c82da71348fd283f1c22cf27f75ef8d",
+ "sha256": "99aa5dd7a288f59c8f6cd7d66df70c62d861d4be2ca0f7f24f8b8ccb3d1133e7"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.7.0-cp35-cp35m-macosx_10_11_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "6c82da71348fd283f1c22cf27f75ef8d",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": null,
+ "size": 97752,
+ "upload_time": "2016-12-07T16:50:46",
+ "url": "https://files.pythonhosted.org/packages/2e/ba/32f32e68c634979bf1a84e1f754b77539168b7d491799c6c2dcd31c552c2/pendulum-0.7.0-cp35-cp35m-macosx_10_11_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "eb9fe95e3110dfb29c93ffb810571f2b",
+ "sha256": "c07576443b25d84fe239050e3fac256d799d886cd5903e6510f328b61b739fe1"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.7.0-cp35-cp35m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "eb9fe95e3110dfb29c93ffb810571f2b",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": null,
+ "size": 106134,
+ "upload_time": "2016-12-07T16:50:48",
+ "url": "https://files.pythonhosted.org/packages/d4/83/0ef7de93077564621f03cdab41b750bacc3ce049823a18caa85e71d58b79/pendulum-0.7.0-cp35-cp35m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "edaabae517287eb0244b5e8590e954df",
+ "sha256": "439b811b555ff7b8ad006d181f2b90d202ecdf2ba732922641f7457322215b47"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.7.0-cp35-cp35m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "edaabae517287eb0244b5e8590e954df",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": null,
+ "size": 105494,
+ "upload_time": "2016-12-07T16:50:51",
+ "url": "https://files.pythonhosted.org/packages/05/2a/8d4beae63894818ee03952399b84a03fa1038f5cf14c8f3dd51183f8ed6e/pendulum-0.7.0-cp35-cp35m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "2e39351134cc186d6e666b3334d6b8d4",
+ "sha256": "81455883f225abd38ef06eb02eb898330f656e9d55106575f9a5b0832b34537c"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.7.0-cp36-cp36m-macosx_10_11_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "2e39351134cc186d6e666b3334d6b8d4",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp36",
+ "requires_python": null,
+ "size": 97752,
+ "upload_time": "2016-12-07T16:50:53",
+ "url": "https://files.pythonhosted.org/packages/c1/5d/fd536df5c477ddc911f8106f2885719642641bfb05a29aa170ee71924c7b/pendulum-0.7.0-cp36-cp36m-macosx_10_11_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "2f099b1e94b6158d275475aaa3002fb2",
+ "sha256": "3cfbfb9c62b05a012f55cc363ce449a9d17388cd3bfbf823f82f4093699e112c"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.7.0.tar.gz",
+ "has_sig": false,
+ "md5_digest": "2f099b1e94b6158d275475aaa3002fb2",
+ "packagetype": "sdist",
+ "python_version": "source",
+ "requires_python": null,
+ "size": 62319,
+ "upload_time": "2016-12-07T16:50:55",
+ "url": "https://files.pythonhosted.org/packages/af/b6/aea118b901b37aceeebb80afbe43ae2db94d605cdd766eee98765ba7f220/pendulum-0.7.0.tar.gz"
+ }
+ ],
+ "0.8.0": [
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "3c5fecf030eeeb3bedc98e9dc0fcf397",
+ "sha256": "7c2ed18ef5fec45b24ba28d98f3bbf77cdd2715daa6f5dd864ff8e6f6e526641"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.8.0-cp27-cp27m-macosx_10_11_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "3c5fecf030eeeb3bedc98e9dc0fcf397",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": null,
+ "size": 101662,
+ "upload_time": "2016-12-23T15:25:02",
+ "url": "https://files.pythonhosted.org/packages/8e/39/14ae7a0d50750415b8d71eeb24c511dc4271707093671fd051bb851d13ef/pendulum-0.8.0-cp27-cp27m-macosx_10_11_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "980d8e3b22f159dcabcf7bcd3852cf91",
+ "sha256": "e89f08dad953ff0c46453d361a1b448b87f684d474f1cec81e00d47bd70c5eaf"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.8.0-cp27-cp27m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "980d8e3b22f159dcabcf7bcd3852cf91",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": null,
+ "size": 109948,
+ "upload_time": "2016-12-23T15:25:05",
+ "url": "https://files.pythonhosted.org/packages/83/59/869c1030278f00307781f1a158b895928840bc87cdd0a1be65e67063b96d/pendulum-0.8.0-cp27-cp27m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "106fea59cd72a947190f6e22aaed4392",
+ "sha256": "0724d38d974b4e30274ae96d386dabc7e449fd0b00cb66879fcf6b12ae97e1be"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.8.0-cp27-cp27m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "106fea59cd72a947190f6e22aaed4392",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": null,
+ "size": 109326,
+ "upload_time": "2016-12-23T15:25:08",
+ "url": "https://files.pythonhosted.org/packages/6e/7d/60f27c9c023c1d7eaad7b7192d277c2b7427da270a3f8cab39e57a86ea3c/pendulum-0.8.0-cp27-cp27m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "ee2d0f32b400388b4204d72d7bbf80ff",
+ "sha256": "8851372708e13c4996aa137d92df9a100a5db6b79c233cd5e6dead68b3fdd1d2"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.8.0-cp35-cp35m-macosx_10_11_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "ee2d0f32b400388b4204d72d7bbf80ff",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": null,
+ "size": 101743,
+ "upload_time": "2016-12-23T15:25:11",
+ "url": "https://files.pythonhosted.org/packages/f2/61/7560f80a3fb860ae1f4a2062348742a293f8c25d343edf374a2ecbe5564c/pendulum-0.8.0-cp35-cp35m-macosx_10_11_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "d6c2a89efa2692d3af86a2dbe60a316d",
+ "sha256": "23d38f54923e65f9a824a2b8e16b0af9a70d323fa18a72f799a078ec68d3c6b9"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.8.0-cp35-cp35m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "d6c2a89efa2692d3af86a2dbe60a316d",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": null,
+ "size": 110125,
+ "upload_time": "2016-12-23T15:25:14",
+ "url": "https://files.pythonhosted.org/packages/4b/e4/106c81376d213f3e95e99e416f6687d1477c56257822a8fced736aa1a08d/pendulum-0.8.0-cp35-cp35m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "f23404cfc085ef8055e5861b1cfa69a4",
+ "sha256": "67e0dc68ad43f9554498ac4ef08d5f1dbe18d021acf19f0764d5adaac7cbf4df"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.8.0-cp35-cp35m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "f23404cfc085ef8055e5861b1cfa69a4",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": null,
+ "size": 109491,
+ "upload_time": "2016-12-23T15:25:17",
+ "url": "https://files.pythonhosted.org/packages/bc/8b/1b50f4e4c34fd343f15fa3ba2c4537fa11382fb02f3571df8ebeb20e24e4/pendulum-0.8.0-cp35-cp35m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "c66059b598a2a0db5778237809b6655d",
+ "sha256": "787c5f472d1498a9caca71ddaaa749da818193923cd286555625f82f8000fe1a"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.8.0-cp36-cp36m-macosx_10_11_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "c66059b598a2a0db5778237809b6655d",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp36",
+ "requires_python": null,
+ "size": 101745,
+ "upload_time": "2016-12-23T15:25:20",
+ "url": "https://files.pythonhosted.org/packages/6e/ac/e462b56ea9979abd49d77e945661e2df80334e50951f6a8eac11e713344f/pendulum-0.8.0-cp36-cp36m-macosx_10_11_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "541974190b0a5e70df5242d9bcedae4f",
+ "sha256": "df13a4c3830d8cf2f09c897a3f84d04c525c1d5aec30b9b9ae9a8abe24b8a29e"
+ },
+ "downloads": -1,
+ "filename": "pendulum-0.8.0.tar.gz",
+ "has_sig": false,
+ "md5_digest": "541974190b0a5e70df5242d9bcedae4f",
+ "packagetype": "sdist",
+ "python_version": "source",
+ "requires_python": null,
+ "size": 65334,
+ "upload_time": "2016-12-23T15:25:24",
+ "url": "https://files.pythonhosted.org/packages/91/9b/4e44fb960418d533bc2df8b5525ab75b602e8b919b9b35580e136fb01c2f/pendulum-0.8.0.tar.gz"
+ }
+ ],
+ "1.0.0": [
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "a2fa5ddd41743b9050fa84b8330b586e",
+ "sha256": "32e00b36bd9555778fab3948d071b565b16c349e17e0857ac5060542a6aa1e97"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.0.0-cp27-cp27m-macosx_10_11_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "a2fa5ddd41743b9050fa84b8330b586e",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": null,
+ "size": 100959,
+ "upload_time": "2017-01-17T19:30:15",
+ "url": "https://files.pythonhosted.org/packages/fb/f9/4945f9b7b93e3a3bd966d8d80d9eab157a8a1add20beb77f2758aac56dc4/pendulum-1.0.0-cp27-cp27m-macosx_10_11_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "d420a878a79e28315b8ba44de87ad7d4",
+ "sha256": "64386a74f3bc592c929e0ff4515ff7bb94bf09c4f42cc6e96bf4ee071c9d356a"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.0.0-cp27-cp27m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "d420a878a79e28315b8ba44de87ad7d4",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": null,
+ "size": 109250,
+ "upload_time": "2017-01-17T19:30:18",
+ "url": "https://files.pythonhosted.org/packages/3d/a8/7ac73c3babe0bd20654d6a07543331159ff6586df6f35d11c5b666260eca/pendulum-1.0.0-cp27-cp27m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "dc5ab9a2758d770bd1fd2c237e676832",
+ "sha256": "6127d0f2008e8155330c16aa9cf6545533bb0f91efee73fcefb09c6f782969e3"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.0.0-cp27-cp27m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "dc5ab9a2758d770bd1fd2c237e676832",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": null,
+ "size": 108625,
+ "upload_time": "2017-01-17T19:30:20",
+ "url": "https://files.pythonhosted.org/packages/ab/47/b159a21474a39af3a8f1d475c523815fe1fe416d54fb5419b32af62358c1/pendulum-1.0.0-cp27-cp27m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "9a042804daf3fece57f4c4dedf95464a",
+ "sha256": "d3e538d8ae6eccd5c86423932dd41264898d1bc81bee9eb53a8607d8afc5c4ab"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.0.0-cp35-cp35m-macosx_10_11_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "9a042804daf3fece57f4c4dedf95464a",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": null,
+ "size": 101041,
+ "upload_time": "2017-01-17T19:30:22",
+ "url": "https://files.pythonhosted.org/packages/cc/64/af870d0bbbc0e79b48b98924c7d31300344202b83eb00b3c4cc252a22f5d/pendulum-1.0.0-cp35-cp35m-macosx_10_11_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "2db24580f4fddf8a64525144913d76be",
+ "sha256": "b849f0fa85e4df25fe77069b0ef0f10148e1f50d8651f2c2c6a879e559046f71"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.0.0-cp35-cp35m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "2db24580f4fddf8a64525144913d76be",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": null,
+ "size": 109421,
+ "upload_time": "2017-01-17T19:30:24",
+ "url": "https://files.pythonhosted.org/packages/a1/6e/26a1965822a95838d341b8976c3a2b01373b0c3c80cafb0c552cd679d256/pendulum-1.0.0-cp35-cp35m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "b812457e65a46ede7a04c51779d70dd9",
+ "sha256": "b74534477f8dee612641ded377064198b9a298cd2efcd492f9de6ff5e89d89ed"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.0.0-cp35-cp35m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "b812457e65a46ede7a04c51779d70dd9",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": null,
+ "size": 108785,
+ "upload_time": "2017-01-17T19:30:27",
+ "url": "https://files.pythonhosted.org/packages/d3/1d/f5e26051744418d46687212c98e572adfd7be6f5e493244646583caedb82/pendulum-1.0.0-cp35-cp35m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "6acd567b83f622fce0bdd6d838cc9609",
+ "sha256": "3b43453f39f569bced312123cfb92bdcedc96172232e25f7f33a76e680898f99"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.0.0-cp36-cp36m-macosx_10_11_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "6acd567b83f622fce0bdd6d838cc9609",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp36",
+ "requires_python": null,
+ "size": 101045,
+ "upload_time": "2017-01-17T19:30:29",
+ "url": "https://files.pythonhosted.org/packages/bf/4a/24fea31866117d29240d3e452af82a147ff5a0c044affd36e22c143b8c0d/pendulum-1.0.0-cp36-cp36m-macosx_10_11_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "57fbe235e4bc54853cbbf6f513e89659",
+ "sha256": "90c2d6ef8f5cfec03a1bbad72a727f28f58f24309033330988b27692f2667be3"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.0.0-cp36-cp36m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "57fbe235e4bc54853cbbf6f513e89659",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp36",
+ "requires_python": null,
+ "size": 109461,
+ "upload_time": "2017-01-17T19:30:31",
+ "url": "https://files.pythonhosted.org/packages/a9/b5/623a4bb52347bf729fb9e3ad1f2fbd9321c3ed759c3621b3d99a621bbf62/pendulum-1.0.0-cp36-cp36m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "a34ac9055e3aab42ea658050c6d06c22",
+ "sha256": "158fbba156884ba54db32e33776dcc0f374d2fe52d4487c3ec0c5890b0960d79"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.0.0-cp36-cp36m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "a34ac9055e3aab42ea658050c6d06c22",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp36",
+ "requires_python": null,
+ "size": 108840,
+ "upload_time": "2017-01-17T19:30:33",
+ "url": "https://files.pythonhosted.org/packages/5c/8d/a2bbfc0f023195e09eb87f44560aa8c7c2b963c20a1cf4c356c8feeb0232/pendulum-1.0.0-cp36-cp36m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "e3db44cfb2be549a7724a387c2803d30",
+ "sha256": "a6968b1ad6a943160f63dba47a896685b8b2977066e5dc102e466d1ab3f93061"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.0.0.tar.gz",
+ "has_sig": false,
+ "md5_digest": "e3db44cfb2be549a7724a387c2803d30",
+ "packagetype": "sdist",
+ "python_version": "source",
+ "requires_python": null,
+ "size": 64881,
+ "upload_time": "2017-01-17T19:30:35",
+ "url": "https://files.pythonhosted.org/packages/90/b7/33ce759a4a8b2543b98a42689b7ce360b2b7ccc67ec1ec8901d97a5feb7a/pendulum-1.0.0.tar.gz"
+ }
+ ],
+ "1.0.1": [
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "a16f2de51b374311b94b853c01f0b77c",
+ "sha256": "ef75794151a862ed14504027f91deb08f9c177a65dec1b888cddd8c256cb5189"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.0.1-cp27-cp27m-macosx_10_11_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "a16f2de51b374311b94b853c01f0b77c",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": null,
+ "size": 101004,
+ "upload_time": "2017-01-25T21:48:32",
+ "url": "https://files.pythonhosted.org/packages/5b/f4/2e46205e7e0ff2f6720ff2cb5fa57f7a349f79dbb73f89e08dd7b9c6f2dc/pendulum-1.0.1-cp27-cp27m-macosx_10_11_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "c03da5273ef6bb01d23a36aefcfb21ea",
+ "sha256": "b83d3978ee9f55383e251ce37cd7cda6aba12e7d08198733b311ae517aa029f4"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.0.1-cp27-cp27m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "c03da5273ef6bb01d23a36aefcfb21ea",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": null,
+ "size": 109294,
+ "upload_time": "2017-01-25T21:48:34",
+ "url": "https://files.pythonhosted.org/packages/85/a3/c16b00c6c95a8a5d3396bcba631591be62d63105b9112219743ce81bceaa/pendulum-1.0.1-cp27-cp27m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "423260ffb47c53fb26cd8cdeec68b599",
+ "sha256": "a11561586193e3ea6015cb41e89648c1474a3fed7f840f1c6f95e43653b4d422"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.0.1-cp27-cp27m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "423260ffb47c53fb26cd8cdeec68b599",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": null,
+ "size": 108665,
+ "upload_time": "2017-01-25T21:48:37",
+ "url": "https://files.pythonhosted.org/packages/c6/35/c93010cd7230773c384db4f496fbee4684b86adf54f9a559cb1c3181a9df/pendulum-1.0.1-cp27-cp27m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "ef64216aba79cacdb4a2e57a2663714d",
+ "sha256": "96d229acc3d72ef9176659b173e3560fb44572bf0ba3e9e83d0b89d8c5a9b734"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.0.1-cp35-cp35m-macosx_10_11_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "ef64216aba79cacdb4a2e57a2663714d",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": null,
+ "size": 101087,
+ "upload_time": "2017-01-25T21:48:39",
+ "url": "https://files.pythonhosted.org/packages/17/86/5462dd28a4c8d90b55456175952ba86d70287ee91720796256fb7637e35e/pendulum-1.0.1-cp35-cp35m-macosx_10_11_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "1c5336e38057a6328e21bc80fa56f996",
+ "sha256": "917555d46ce8619fed0130415afb0b17dbad500076972ca014d91f4059c66291"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.0.1-cp35-cp35m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "1c5336e38057a6328e21bc80fa56f996",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": null,
+ "size": 109471,
+ "upload_time": "2017-01-25T21:48:41",
+ "url": "https://files.pythonhosted.org/packages/54/dc/1976c0db248ceae5d2a6d0e54983592bebfde53a48f2a4efb9446596a7c6/pendulum-1.0.1-cp35-cp35m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "daa325667f721e4d81612bf3074373d3",
+ "sha256": "7e8486cfe4abbf9890bab9ed3f90a328d0b17cb49b8f6ad37adca6ceae9775e2"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.0.1-cp35-cp35m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "daa325667f721e4d81612bf3074373d3",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": null,
+ "size": 108830,
+ "upload_time": "2017-01-25T21:48:44",
+ "url": "https://files.pythonhosted.org/packages/91/76/1832d4f6c2647629d64eae6e2615181c894aeae6c230d625a1325836a776/pendulum-1.0.1-cp35-cp35m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "64c8abe461cbae9a1e0563f69b06ab09",
+ "sha256": "b6c837c2d6e3797b232a80704c23f777072bcddb6e996f00b3ed1180a2df73c6"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.0.1-cp36-cp36m-macosx_10_11_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "64c8abe461cbae9a1e0563f69b06ab09",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp36",
+ "requires_python": null,
+ "size": 101088,
+ "upload_time": "2017-01-25T21:48:46",
+ "url": "https://files.pythonhosted.org/packages/7f/64/c16d0338cc54f33868bf1dade8984cbe33f7e70165f859771637e65af74a/pendulum-1.0.1-cp36-cp36m-macosx_10_11_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "849f1af9bfbfb4797f96ead8f0c48d86",
+ "sha256": "fd466c456bdf40ab6927daf69a9d14444b990e17adea510fa8a3e188743ef4f5"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.0.1-cp36-cp36m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "849f1af9bfbfb4797f96ead8f0c48d86",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp36",
+ "requires_python": null,
+ "size": 109505,
+ "upload_time": "2017-01-25T21:48:49",
+ "url": "https://files.pythonhosted.org/packages/cc/1d/f26eeae43a785493af2dafb7d0a8d32ccc8f55b8cdfa5ee26e112e96d778/pendulum-1.0.1-cp36-cp36m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "738fae0668285cebd3b2049e0989d81c",
+ "sha256": "cf7c12207632175d0f270bdae536913ed88a13fd85d3fe35a6e460e93c0b027b"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.0.1-cp36-cp36m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "738fae0668285cebd3b2049e0989d81c",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp36",
+ "requires_python": null,
+ "size": 108885,
+ "upload_time": "2017-01-25T21:48:51",
+ "url": "https://files.pythonhosted.org/packages/44/6d/1f055ae6c71936197856ebb8f67b26a535874eb126ae7ddc53bb5e4365f7/pendulum-1.0.1-cp36-cp36m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "0ebd78e435cf15a8679b5f6191a1e4cb",
+ "sha256": "33f3e2bd60b0211fef40564c0f2643edb69906fc795d4aa2fd1a5a4a18dd1173"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.0.1.tar.gz",
+ "has_sig": false,
+ "md5_digest": "0ebd78e435cf15a8679b5f6191a1e4cb",
+ "packagetype": "sdist",
+ "python_version": "source",
+ "requires_python": null,
+ "size": 64944,
+ "upload_time": "2017-01-25T21:48:53",
+ "url": "https://files.pythonhosted.org/packages/a4/b9/66e0ecd85f628d1f0a4f4027b70ad858e22420031dd4b087d7540e64d7af/pendulum-1.0.1.tar.gz"
+ }
+ ],
+ "1.0.2": [
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "abce95f440609259c5c720d8fda2a652",
+ "sha256": "f272f2d62a0f0ad0f6e741a07c46517eaa0a9d6cf352d383c4dd8ee47df9a853"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.0.2-cp27-cp27m-macosx_10_11_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "abce95f440609259c5c720d8fda2a652",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": null,
+ "size": 101111,
+ "upload_time": "2017-02-04T19:32:42",
+ "url": "https://files.pythonhosted.org/packages/d8/1e/894eb92323f2ecde7c8f9bb4963f0cb92a2f5bc25a776b1ada7e6836e751/pendulum-1.0.2-cp27-cp27m-macosx_10_11_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "00f3ecdd57a13b650c97ac6dccc032ea",
+ "sha256": "ecc1eb50ec645b2ace6e9680822ed2c5f7d1bd0928788cdae793780cf8be25af"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.0.2-cp27-cp27m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "00f3ecdd57a13b650c97ac6dccc032ea",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": null,
+ "size": 109395,
+ "upload_time": "2017-02-04T19:32:44",
+ "url": "https://files.pythonhosted.org/packages/78/53/de1fca872747ecdcc538c36412fef9e201b1efcac32d1ee592cd06103070/pendulum-1.0.2-cp27-cp27m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "ddbbb16d5a5d32e6fda43f69fa14358d",
+ "sha256": "28eb16dce2e01b06885259306cef8d7f8e7f4c2f85cb13491c448c620e33b123"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.0.2-cp27-cp27m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "ddbbb16d5a5d32e6fda43f69fa14358d",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": null,
+ "size": 108767,
+ "upload_time": "2017-02-04T19:32:46",
+ "url": "https://files.pythonhosted.org/packages/bc/27/e7a21861dbd9be2777147481fad4946e2ae56a7bac8feb995f1776cb4664/pendulum-1.0.2-cp27-cp27m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "88ee4bf193495eaa273d2d13be8c53fb",
+ "sha256": "7ef63a6560cb9c0c311710d6f9568797874883970996f70147b538039399174b"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.0.2-cp35-cp35m-macosx_10_11_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "88ee4bf193495eaa273d2d13be8c53fb",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": null,
+ "size": 101187,
+ "upload_time": "2017-02-04T19:32:49",
+ "url": "https://files.pythonhosted.org/packages/b1/b6/26ce9bad7a625f1f9b8e732a4725ec5413f4ca917825f7391e16cd6a9a17/pendulum-1.0.2-cp35-cp35m-macosx_10_11_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "c9e8a428ee173b938c8f5a3d000106a9",
+ "sha256": "2f720ff6708036d43d3a9508005ac020b1ab9375e785248ec96520fe25cf38cf"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.0.2-cp35-cp35m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "c9e8a428ee173b938c8f5a3d000106a9",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": null,
+ "size": 109572,
+ "upload_time": "2017-02-04T19:32:51",
+ "url": "https://files.pythonhosted.org/packages/5f/a2/ee4f6323cbf751e9f51fbcdeba95b7c8299a8e00577d3cb5d1b84f2e0907/pendulum-1.0.2-cp35-cp35m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "b5f37b12e1de4e7a806a16bdedc406b1",
+ "sha256": "9f9c7e7f96d9213487c979b38a862834f30a4cabf4be1114d0f1dece670a3b6f"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.0.2-cp35-cp35m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "b5f37b12e1de4e7a806a16bdedc406b1",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": null,
+ "size": 108935,
+ "upload_time": "2017-02-04T19:32:53",
+ "url": "https://files.pythonhosted.org/packages/d8/46/0821b87121b865f273a66d6820deadc714882ba5e6f769267d5115da047c/pendulum-1.0.2-cp35-cp35m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "bb9e1cf40571446462de0e5a073aa43e",
+ "sha256": "2417888ceddbb9c3903317ad321e27b2217aacf4ddcc1993ac3ad4db96f3a701"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.0.2-cp36-cp36m-macosx_10_11_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "bb9e1cf40571446462de0e5a073aa43e",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp36",
+ "requires_python": null,
+ "size": 101193,
+ "upload_time": "2017-02-04T19:32:56",
+ "url": "https://files.pythonhosted.org/packages/fe/a9/35a0491f28d44c2db9812fbd119c93cb10429253bc41ecd9abced8035ee8/pendulum-1.0.2-cp36-cp36m-macosx_10_11_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "58e6229c5cf2846eb683df93198263de",
+ "sha256": "abf600469c11cf6c265283b2f948668b9cb1343aa823f20688ad2c81904a950c"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.0.2-cp36-cp36m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "58e6229c5cf2846eb683df93198263de",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp36",
+ "requires_python": null,
+ "size": 109607,
+ "upload_time": "2017-02-04T19:32:58",
+ "url": "https://files.pythonhosted.org/packages/d9/49/58dc99e6e613092b7081ffd8b450935c3d80c01c0635e1e693616d6ee2d5/pendulum-1.0.2-cp36-cp36m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "eb89f94168441ac293d18b2074898266",
+ "sha256": "2b983cdf91b2ecde69893bef4cdc092f0f9f4ef6fd854cd3258a295e15254501"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.0.2-cp36-cp36m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "eb89f94168441ac293d18b2074898266",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp36",
+ "requires_python": null,
+ "size": 108988,
+ "upload_time": "2017-02-04T19:33:00",
+ "url": "https://files.pythonhosted.org/packages/ad/de/cb218438ee1d6f77ff3c1ca0c5b8700d971e3c9557524f62869ea2d3e945/pendulum-1.0.2-cp36-cp36m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "0112fbd931e0c39e58c39e68f0bdf2bc",
+ "sha256": "4cb83d6e248cddd4dd71c91b8eec58ebee8823ac0c370142903ef2d554bd8b8c"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.0.2.tar.gz",
+ "has_sig": false,
+ "md5_digest": "0112fbd931e0c39e58c39e68f0bdf2bc",
+ "packagetype": "sdist",
+ "python_version": "source",
+ "requires_python": null,
+ "size": 65038,
+ "upload_time": "2017-02-04T19:33:03",
+ "url": "https://files.pythonhosted.org/packages/fc/40/97cceb43716baa8c23b0636a226b33ed7754c9e7469ca2a436ef0cfc99d1/pendulum-1.0.2.tar.gz"
+ }
+ ],
+ "1.1.0": [
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "4648cf5c27cad8cf7b46f7d9258b66ab",
+ "sha256": "9acc8bd95021994cc2a8cbfe701ec839f0492dc356e7139f421f92137f541aef"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.1.0-cp27-cp27m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "4648cf5c27cad8cf7b46f7d9258b66ab",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": null,
+ "size": 110398,
+ "upload_time": "2017-02-20T19:36:28",
+ "url": "https://files.pythonhosted.org/packages/d6/de/451ab94d6c39b8dd925dcffacf11841eacd6f1557f97582eac52ef81b194/pendulum-1.1.0-cp27-cp27m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "b231d46264681a28b436f65cda01d7a3",
+ "sha256": "023cbbcc429e4fd7ba03437917c9c25ae020f8c3def2caacbf5666f0fbb9a4fc"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.1.0-cp27-cp27m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "b231d46264681a28b436f65cda01d7a3",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": null,
+ "size": 109763,
+ "upload_time": "2017-02-20T19:36:32",
+ "url": "https://files.pythonhosted.org/packages/5e/93/bb3e22cc270927931c0ba5a04a0b952d5711786849f811b6f4a6dea39bca/pendulum-1.1.0-cp27-cp27m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "dadc1b44e557964579e9e11a944378d3",
+ "sha256": "f4aadf4a93667af461fb91c630fbfe978c8a620e5ee4d1982615bcf307d22ba4"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.1.0-cp35-cp35m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "dadc1b44e557964579e9e11a944378d3",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": null,
+ "size": 110566,
+ "upload_time": "2017-02-20T19:36:35",
+ "url": "https://files.pythonhosted.org/packages/0c/7e/e925677f43147ad23d9b3b0d23b6b85a4f206c4c59ac13bf5a42f0a770d2/pendulum-1.1.0-cp35-cp35m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "a79d9401a61e15c4540b46896910d29e",
+ "sha256": "6cd037d885f06c9055aa21f89d6e57ae22d07bf7c6c09aa00aa15c27a2a58a13"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.1.0-cp35-cp35m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "a79d9401a61e15c4540b46896910d29e",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": null,
+ "size": 109933,
+ "upload_time": "2017-02-20T19:36:38",
+ "url": "https://files.pythonhosted.org/packages/87/be/9edb6dd58f636c2828fe0fefaf21d1652063b0d57035bc2f4abb6719ef68/pendulum-1.1.0-cp35-cp35m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "4634fa7a95d5050a9f56066e8ef8fbe5",
+ "sha256": "0ea1ef22f05da98241b89d0a60dd68425c19233c34f1887fe87670d1747c422e"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.1.0-cp36-cp36m-macosx_10_11_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "4634fa7a95d5050a9f56066e8ef8fbe5",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp36",
+ "requires_python": null,
+ "size": 102184,
+ "upload_time": "2017-02-20T19:36:41",
+ "url": "https://files.pythonhosted.org/packages/19/95/bd587394c6248cde13e4ee37ff91c43e43003c13ae38b8dbee9fcd6df0ee/pendulum-1.1.0-cp36-cp36m-macosx_10_11_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "fb8e2186e2894f9d305d4d300170fa7e",
+ "sha256": "ff38fe9e7b632c4818a5fa05e1246c9519029e3c623514716307e4012d3908f5"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.1.0-cp36-cp36m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "fb8e2186e2894f9d305d4d300170fa7e",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp36",
+ "requires_python": null,
+ "size": 110607,
+ "upload_time": "2017-02-20T19:36:43",
+ "url": "https://files.pythonhosted.org/packages/b5/92/e3fd999432a2842ab610fee22aebb5897b215ef9a32717f408087485ccb2/pendulum-1.1.0-cp36-cp36m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "ac63a3b9ba19a73e7171aff3d8243c2f",
+ "sha256": "06ac3ee1b2f09a55697540b5c0dbe446f895521dddfd3266dfa2bf4eb1eb1b67"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.1.0-cp36-cp36m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "ac63a3b9ba19a73e7171aff3d8243c2f",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp36",
+ "requires_python": null,
+ "size": 109988,
+ "upload_time": "2017-02-20T19:36:45",
+ "url": "https://files.pythonhosted.org/packages/49/54/3e4bdc3107763f9396e1f9bf60c511ff1e56017ee1d6b6a01efceec91702/pendulum-1.1.0-cp36-cp36m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "a5848d81e5342dadef09888a0e32494e",
+ "sha256": "be9fe8380a48166a23122a5d29529eca3df3adb09dd85ea939db0dc651b9f187"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.1.0.tar.gz",
+ "has_sig": false,
+ "md5_digest": "a5848d81e5342dadef09888a0e32494e",
+ "packagetype": "sdist",
+ "python_version": "source",
+ "requires_python": null,
+ "size": 65586,
+ "upload_time": "2017-02-20T19:36:47",
+ "url": "https://files.pythonhosted.org/packages/fc/21/1c7307f52215b34e63c43eae2a21b71bb2b4e5bf80baffd851dae849a572/pendulum-1.1.0.tar.gz"
+ }
+ ],
+ "1.1.1": [
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "8ce36e495f89067b6491e5082d69e1be",
+ "sha256": "9da300cbe5a2bc603c346ecf59dc48400ea72d0a48be58776574d78ccd5d7a70"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.1.1-cp27-cp27m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "8ce36e495f89067b6491e5082d69e1be",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": null,
+ "size": 110441,
+ "upload_time": "2017-03-14T19:54:02",
+ "url": "https://files.pythonhosted.org/packages/7d/51/403e8845516f40166fe0f8df18e23e58e39ed81928f443900754d8c329d5/pendulum-1.1.1-cp27-cp27m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "a810ceaf8fb2763b9ac45427f70eddf8",
+ "sha256": "1e188f2373af98cebb9decf3a482bb971d5b0a6cfe56edebc044be3292b3a7ea"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.1.1-cp27-cp27m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "a810ceaf8fb2763b9ac45427f70eddf8",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": null,
+ "size": 109815,
+ "upload_time": "2017-03-14T19:54:04",
+ "url": "https://files.pythonhosted.org/packages/ee/24/21075d76600e6fd82a319948f0a4e6d3b04f6624756e4dc45ac423093ad8/pendulum-1.1.1-cp27-cp27m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "96f2b40df63e8d150189d9d591f4cb5a",
+ "sha256": "f3ec40b2b539c5152efabe749c24e53afc4856291cc405fcdd69fd1f9db569eb"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.1.1-cp35-cp35m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "96f2b40df63e8d150189d9d591f4cb5a",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": null,
+ "size": 110619,
+ "upload_time": "2017-03-14T19:54:07",
+ "url": "https://files.pythonhosted.org/packages/6a/46/4a6f1bfc59d5419ed5968f8e1fb71f60d791e70416b0fc24e2b744f310ee/pendulum-1.1.1-cp35-cp35m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "0bf2cf442179b8afd2d72acde929bfcc",
+ "sha256": "9be1765e512d9d7ba1738d07b689826ae89800511e629ff8ee40c7ec7f6eadd1"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.1.1-cp35-cp35m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "0bf2cf442179b8afd2d72acde929bfcc",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": null,
+ "size": 109987,
+ "upload_time": "2017-03-14T19:54:08",
+ "url": "https://files.pythonhosted.org/packages/9f/ac/3443fefda61848cd299e051133c829090457cfe718d48d1eef2beaba6c3b/pendulum-1.1.1-cp35-cp35m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "e72c77e46e142f900028aa6a1448244b",
+ "sha256": "c72e1a869830aeb79e4c1675b52da07f6537c625b1421902180bb262dbe14ca0"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.1.1-cp36-cp36m-macosx_10_11_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "e72c77e46e142f900028aa6a1448244b",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp36",
+ "requires_python": null,
+ "size": 102236,
+ "upload_time": "2017-03-14T19:54:10",
+ "url": "https://files.pythonhosted.org/packages/08/d3/3a6c59b829a66f9c25be0d01db92f52c9d35f781e56e809684fa866468db/pendulum-1.1.1-cp36-cp36m-macosx_10_11_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "c4228d605b9ced3b7e3a5f5055022c80",
+ "sha256": "243e85cadb1ba7366f5287962de5a2aba9f98dc46f53e7b134d5dedc9c1a3f80"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.1.1-cp36-cp36m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "c4228d605b9ced3b7e3a5f5055022c80",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp36",
+ "requires_python": null,
+ "size": 110664,
+ "upload_time": "2017-03-14T19:54:12",
+ "url": "https://files.pythonhosted.org/packages/a8/e2/0098e6e7f2db33e4338dccc07028702549ea2cc11f4583591a2e500f3c11/pendulum-1.1.1-cp36-cp36m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "ef35b66ee622f5b67f7c9300065e1dc4",
+ "sha256": "c39e873acf4a2d6dc248e8c4f1a837b9fcb815d373f02ecbf2757b18075c4a0e"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.1.1-cp36-cp36m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "ef35b66ee622f5b67f7c9300065e1dc4",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp36",
+ "requires_python": null,
+ "size": 110034,
+ "upload_time": "2017-03-14T19:54:14",
+ "url": "https://files.pythonhosted.org/packages/95/09/11d0f632341fbdea5b4c164c919791edda563db976c2d168e29b541f5634/pendulum-1.1.1-cp36-cp36m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "bf4677d0ec9dc139fd0999bf3a1e8d3c",
+ "sha256": "eaa1448acc5158ebb778a8f1eb80869df89d4af8763c2cf32dcce0c4fec040c8"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.1.1.tar.gz",
+ "has_sig": false,
+ "md5_digest": "bf4677d0ec9dc139fd0999bf3a1e8d3c",
+ "packagetype": "sdist",
+ "python_version": "source",
+ "requires_python": null,
+ "size": 66063,
+ "upload_time": "2017-03-14T19:54:16",
+ "url": "https://files.pythonhosted.org/packages/c3/60/cb9158ea26092fd65f6dbc0eb642173ff54cef11b4fb81e5404e6a97ed0b/pendulum-1.1.1.tar.gz"
+ }
+ ],
+ "1.2.0": [
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "96ec19b7acc0e86157df92a75fc4922d",
+ "sha256": "e467bec4ec56436654499f52789b11d9e15b2bbbb0696a4ee4b6b654fe72d66f"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.2.0-cp27-cp27m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "96ec19b7acc0e86157df92a75fc4922d",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": null,
+ "size": 123815,
+ "upload_time": "2017-03-24T20:18:04",
+ "url": "https://files.pythonhosted.org/packages/4a/cc/e897d0a073e2b30d3fa16f65d972e4f9efeac49783b07f7262cb081e8f5d/pendulum-1.2.0-cp27-cp27m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "183d68765600794a553777b27be7fb4a",
+ "sha256": "ce6c764ba2acaf185a2e4bb02220ac986ad371ea6e7a9d9e42ad882c6d788e0a"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.2.0-cp27-cp27m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "183d68765600794a553777b27be7fb4a",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": null,
+ "size": 124012,
+ "upload_time": "2017-03-24T20:18:06",
+ "url": "https://files.pythonhosted.org/packages/da/94/503e3bf13a8f4aead6db43a5c2a16477e0e5d9b69d384ed91ff4f6e45950/pendulum-1.2.0-cp27-cp27m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "7e0ad6e3178ae66d90f2edd7fae8aacf",
+ "sha256": "925ff1a3094d3517928a5ffca92cf0b0c9016f289133129433c9be0eede937ec"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.2.0-cp35-cp35m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "7e0ad6e3178ae66d90f2edd7fae8aacf",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": null,
+ "size": 124103,
+ "upload_time": "2017-03-24T20:18:08",
+ "url": "https://files.pythonhosted.org/packages/34/41/093acdab1159bd54e2bf7e30588f21de6d52f93ccd10f6aef86f8993c141/pendulum-1.2.0-cp35-cp35m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "37b1dbe1508a7f9760e2a99041f68830",
+ "sha256": "93a5a66cea7222e8388fcb52947ff2e230e7194815baa43b5f85c7e56611b515"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.2.0-cp35-cp35m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "37b1dbe1508a7f9760e2a99041f68830",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": null,
+ "size": 124221,
+ "upload_time": "2017-03-24T20:18:10",
+ "url": "https://files.pythonhosted.org/packages/36/0e/fd4aa96f65216a9b558b9af320f6a2eb98a15369da4a5e3838a410862047/pendulum-1.2.0-cp35-cp35m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "02b069ae8a328d6eab9cd793422b0332",
+ "sha256": "a97e3ed9557ac0c5c3742f21fa4d852d7a050dd9b1b517e993aebef2dd2eea52"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.2.0-cp36-cp36m-macosx_10_11_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "02b069ae8a328d6eab9cd793422b0332",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp36",
+ "requires_python": null,
+ "size": 110238,
+ "upload_time": "2017-03-24T20:18:12",
+ "url": "https://files.pythonhosted.org/packages/50/1c/1b8e56a9814f3382a38e0eb61bbb5ed8fcd07342ac74c6436be006dfb2cb/pendulum-1.2.0-cp36-cp36m-macosx_10_11_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "3e6913c150e74cdb2a488995606e158f",
+ "sha256": "ce67c0777a9f7340e5c6884faf19e571772fe0969c978044bbae601bd0f70873"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.2.0-cp36-cp36m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "3e6913c150e74cdb2a488995606e158f",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp36",
+ "requires_python": null,
+ "size": 124149,
+ "upload_time": "2017-03-24T20:18:16",
+ "url": "https://files.pythonhosted.org/packages/3b/64/5bc08fd29e7fded39187c425226652df6ba3c7efdf39fb8a22296b6d7f01/pendulum-1.2.0-cp36-cp36m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "484b09e5ecd70f220454bff78723ad9a",
+ "sha256": "1d7eb559133e3aa0e2f62fe44e143398c05debce6fabca95732225a58700bec3"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.2.0-cp36-cp36m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "484b09e5ecd70f220454bff78723ad9a",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp36",
+ "requires_python": null,
+ "size": 124283,
+ "upload_time": "2017-03-24T20:18:20",
+ "url": "https://files.pythonhosted.org/packages/1d/a7/493c1ac39e626e76f941878bc5ea287ac209244f9de7958f5c05d5bacf45/pendulum-1.2.0-cp36-cp36m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "2e33ade37806bddee5e12c3717c090c6",
+ "sha256": "641140a05f959b37a177866e263f6f53a53b711fae6355336ee832ec1a59da8a"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.2.0.tar.gz",
+ "has_sig": false,
+ "md5_digest": "2e33ade37806bddee5e12c3717c090c6",
+ "packagetype": "sdist",
+ "python_version": "source",
+ "requires_python": null,
+ "size": 70332,
+ "upload_time": "2017-03-24T20:18:22",
+ "url": "https://files.pythonhosted.org/packages/bd/76/df64385be0590c4b5d8dd424df391bac39c6d931bd4ef497d5931dca64b1/pendulum-1.2.0.tar.gz"
+ }
+ ],
+ "1.2.1": [
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "e5f71e17a775b239d0040aa3dbcce94e",
+ "sha256": "2d3bf48adbce0064f940990e701d7c89dba6c19d13f76967085aa09e7b7aeb85"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.2.1-cp27-cp27m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "e5f71e17a775b239d0040aa3dbcce94e",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": null,
+ "size": 123810,
+ "upload_time": "2017-05-23T20:32:33",
+ "url": "https://files.pythonhosted.org/packages/dd/13/6af2746516f82f4b6ce59fc0848bf8f24f033c31be48b013d3fdb9dbfdca/pendulum-1.2.1-cp27-cp27m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "b549017a053cd8832c21537b319d7776",
+ "sha256": "c93a564788734033279be023b12d50bcc313c9d0a6885df319691cc2bf906e68"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.2.1-cp27-cp27m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "b549017a053cd8832c21537b319d7776",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": null,
+ "size": 124005,
+ "upload_time": "2017-05-23T20:32:35",
+ "url": "https://files.pythonhosted.org/packages/c4/3a/4ed88507edce03ea2f8d33511c3d2140b17124ea6d9945e3394d73417a43/pendulum-1.2.1-cp27-cp27m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "aad7e8384129ad3ca87d603c6e68949f",
+ "sha256": "97a0059ad41d24881974f0fe6d76c26ae5af0b3de4545b85293d84ff75adb1f7"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.2.1-cp35-cp35m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "aad7e8384129ad3ca87d603c6e68949f",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": null,
+ "size": 124095,
+ "upload_time": "2017-05-23T20:32:37",
+ "url": "https://files.pythonhosted.org/packages/dc/ad/02993421aa099dabdf4d596afa6d10121aad7bfb4981aec9b3869f189b74/pendulum-1.2.1-cp35-cp35m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "24658404c71e6c3c9756b812d03f11c0",
+ "sha256": "1b549ecedc8eedd0dfc92b70125233e5dd78110ce854c7df3de9152f5b4b0af4"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.2.1-cp35-cp35m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "24658404c71e6c3c9756b812d03f11c0",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": null,
+ "size": 124215,
+ "upload_time": "2017-05-23T20:32:40",
+ "url": "https://files.pythonhosted.org/packages/25/c7/5ef5cf6729c974b46c7e3e808662a2f32c297cc27bdb723cbe692a4f0f34/pendulum-1.2.1-cp35-cp35m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "4e5b1eaedcf73ce2410853ca9ce85348",
+ "sha256": "6b3263cd975fd501923eb85ed38dc44c08541f7eb3336a6c9e7a4c086cd0a918"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.2.1-cp36-cp36m-macosx_10_11_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "4e5b1eaedcf73ce2410853ca9ce85348",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp36",
+ "requires_python": null,
+ "size": 110227,
+ "upload_time": "2017-05-23T20:32:42",
+ "url": "https://files.pythonhosted.org/packages/58/44/cadb0b500f5f513e8b1b2f23b1d49b5a57a32fc51ce3a137d853e8628c68/pendulum-1.2.1-cp36-cp36m-macosx_10_11_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "23264f8258aabd45cf677cfa1bcdb86e",
+ "sha256": "7058cf10b647a681f7f6e1fc199ade56ab60c4dfff5130e790bf9cd25f6130f5"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.2.1-cp36-cp36m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "23264f8258aabd45cf677cfa1bcdb86e",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp36",
+ "requires_python": null,
+ "size": 124133,
+ "upload_time": "2017-05-23T20:32:44",
+ "url": "https://files.pythonhosted.org/packages/f4/35/76447df5dd6e262fcd12297a8247863f25b61eb18b99a9c2abd4311a79be/pendulum-1.2.1-cp36-cp36m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "46cd2fefe709ecb9913d755b61372187",
+ "sha256": "5aa98251cbac2fb02e3371975a5c49c0eb5a890627ccab467d2af59ab6554b27"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.2.1-cp36-cp36m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "46cd2fefe709ecb9913d755b61372187",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp36",
+ "requires_python": null,
+ "size": 124274,
+ "upload_time": "2017-05-23T20:32:46",
+ "url": "https://files.pythonhosted.org/packages/48/b6/6f2157ff980d60a46f10ab8dfb71e6106812c9481eeecad5a724d64882c2/pendulum-1.2.1-cp36-cp36m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "54b910d69b213bad2c2a78093aad11cf",
+ "sha256": "2e5e7c16de3c0f75a5e6394e9c4f1fecab482a65b2d4381f9d3779315df7ac80"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.2.1.tar.gz",
+ "has_sig": false,
+ "md5_digest": "54b910d69b213bad2c2a78093aad11cf",
+ "packagetype": "sdist",
+ "python_version": "source",
+ "requires_python": null,
+ "size": 70103,
+ "upload_time": "2017-05-23T20:32:48",
+ "url": "https://files.pythonhosted.org/packages/00/dc/fa72f6cee77b5cf5907e82ad7164932963b25fdb23e09e1dde2651cc7eae/pendulum-1.2.1.tar.gz"
+ }
+ ],
+ "1.2.2": [
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "8b7864949f5f6ffc4b7955588a32feb4",
+ "sha256": "01040c82e06e905806392e7857e53088a6d2bbea4a5eac9935a1bc54f30092c7"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.2.2-cp27-cp27m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "8b7864949f5f6ffc4b7955588a32feb4",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": null,
+ "size": 123957,
+ "upload_time": "2017-06-15T16:42:00",
+ "url": "https://files.pythonhosted.org/packages/fa/80/e7dd077bb4494ac3d31db90694b575dbead595b05354156a921d28a8e083/pendulum-1.2.2-cp27-cp27m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "3142ccbe5791c3834a899a04f18dddcb",
+ "sha256": "ac5b7a06de2bf3120290caaa0741e28a413313cb9943d40e17a66c592e3ea169"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.2.2-cp27-cp27m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "3142ccbe5791c3834a899a04f18dddcb",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": null,
+ "size": 124157,
+ "upload_time": "2017-06-15T16:42:02",
+ "url": "https://files.pythonhosted.org/packages/5e/74/514d9460f69ebcdf59062687d08e669cec33976e1f877e431a1f4bc617cb/pendulum-1.2.2-cp27-cp27m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "47cd59c16adbdfed5005decf02a41a2f",
+ "sha256": "e46a9c442f15ebbc14da6a855a896065430e82549ccb69c2d406bcc1e1f2d8e2"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.2.2-cp35-cp35m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "47cd59c16adbdfed5005decf02a41a2f",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": null,
+ "size": 124244,
+ "upload_time": "2017-06-15T16:42:05",
+ "url": "https://files.pythonhosted.org/packages/0d/72/30edae44408f1c6c449911da0d8b814eee37cc4952183623886e197416ac/pendulum-1.2.2-cp35-cp35m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "dfe58e5725b60343a48bae0f156061ab",
+ "sha256": "42fc6d1035e5c2640cd0560f1e0bd786aa5d81dbc71ae0d72204d2d2c73cf2b3"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.2.2-cp35-cp35m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "dfe58e5725b60343a48bae0f156061ab",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": null,
+ "size": 124373,
+ "upload_time": "2017-06-15T16:42:08",
+ "url": "https://files.pythonhosted.org/packages/3e/01/239eddf514932b77646c35864cf92eda5d7b12ac535b4842b71f64a6dd35/pendulum-1.2.2-cp35-cp35m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "16cdc4937c77b68b2089426aac108b08",
+ "sha256": "518273031c4e23c1849539df072e88855ad745d63b53d554d1feb2aecd4aedc0"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.2.2-cp36-cp36m-macosx_10_11_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "16cdc4937c77b68b2089426aac108b08",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp36",
+ "requires_python": null,
+ "size": 110377,
+ "upload_time": "2017-06-15T16:42:10",
+ "url": "https://files.pythonhosted.org/packages/8f/cb/9fa044755bf1d77b98f89472fa97a4dfbe26f51ce3e77fa78d2b586e1470/pendulum-1.2.2-cp36-cp36m-macosx_10_11_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "0d30bb75337655a67ddfda5fc6a31681",
+ "sha256": "3b70a38f612a1cc51df32bef1b37022e32208a392ace491853cd1799831f86cf"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.2.2-cp36-cp36m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "0d30bb75337655a67ddfda5fc6a31681",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp36",
+ "requires_python": null,
+ "size": 124289,
+ "upload_time": "2017-06-15T16:42:12",
+ "url": "https://files.pythonhosted.org/packages/98/d9/d46c79c5172c77f5e2d82655392ecf70d840529e2eed5f439ab8b6f08958/pendulum-1.2.2-cp36-cp36m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "41b7bb3bea401b4bd8446f00698fc8f2",
+ "sha256": "dacefb5a42a7ab089fec8820876cca69cc460294a49bdd0d3fdf646ff7313464"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.2.2-cp36-cp36m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "41b7bb3bea401b4bd8446f00698fc8f2",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp36",
+ "requires_python": null,
+ "size": 124426,
+ "upload_time": "2017-06-15T16:42:15",
+ "url": "https://files.pythonhosted.org/packages/fa/c6/7913c056bef14f01a1f26bfc7a642e924079813d4cf2248473bda9037ff1/pendulum-1.2.2-cp36-cp36m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "4a87fa6ac7dc900d6935a46f21414776",
+ "sha256": "c663d06dd635de79237a1eebcec198757dc2a12c9b3d8ff07c094c3b32dcec36"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.2.2.tar.gz",
+ "has_sig": false,
+ "md5_digest": "4a87fa6ac7dc900d6935a46f21414776",
+ "packagetype": "sdist",
+ "python_version": "source",
+ "requires_python": null,
+ "size": 70233,
+ "upload_time": "2017-06-15T16:42:17",
+ "url": "https://files.pythonhosted.org/packages/98/b8/225ce8d0e1aaae0edd35d6e63bbd446b5663dad43fe6d01b786c1e6c07e2/pendulum-1.2.2.tar.gz"
+ }
+ ],
+ "1.2.3": [
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "8f2e8cfe982a41f2a23021630003574e",
+ "sha256": "4198d6614fc9ff5680cacd131d4d210a27c572fdca3d1599e8ce7e38fad1c97e"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.2.3-cp27-cp27m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "8f2e8cfe982a41f2a23021630003574e",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": null,
+ "size": 123993,
+ "upload_time": "2017-06-19T00:39:01",
+ "url": "https://files.pythonhosted.org/packages/3b/24/3a7f0599912a1988c385bcb747d9055d28ddf5b8a7b52aea52cb664aee93/pendulum-1.2.3-cp27-cp27m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "1c7bece18ed5284c6212ef7740a7c8b7",
+ "sha256": "43cf3c9285cdf59628a1cf9f6c550e511dc97f79decfcb0238e9a8164dcd2b20"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.2.3-cp27-cp27m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "1c7bece18ed5284c6212ef7740a7c8b7",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": null,
+ "size": 124175,
+ "upload_time": "2017-06-19T00:39:04",
+ "url": "https://files.pythonhosted.org/packages/16/43/8b34bdd08cc63c3f2cab6edc9860d6754cef743430a588822379fd71e59a/pendulum-1.2.3-cp27-cp27m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "a5ba61ad75f0b940c6e71ae1ed49ae55",
+ "sha256": "523115445ce17045fcea0d4a7da550f9065031a4ea8673bba9e38d1f16ecce02"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.2.3-cp35-cp35m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "a5ba61ad75f0b940c6e71ae1ed49ae55",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": null,
+ "size": 124277,
+ "upload_time": "2017-06-19T00:39:06",
+ "url": "https://files.pythonhosted.org/packages/54/74/4c469a9ba4f7d62ef0daa6198a3576edfb87141040b5e0b2ca28ce34fb9d/pendulum-1.2.3-cp35-cp35m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "17a5a495b818012f299dbad57df63f64",
+ "sha256": "1c939fddd1b436917ffd7d11956d3bcc634cea573b55c29b11a2465902e866b4"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.2.3-cp35-cp35m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "17a5a495b818012f299dbad57df63f64",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": null,
+ "size": 124396,
+ "upload_time": "2017-06-19T00:39:08",
+ "url": "https://files.pythonhosted.org/packages/8f/94/2f83e88cce617e1757474c197702339716c251bc2b2f6ce698d47c228c56/pendulum-1.2.3-cp35-cp35m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "688fd1eb6bd03135e7ff4af1c15b5949",
+ "sha256": "d2a48c8d498399fe8476199a499347a2c1a73b0564f58eb71d11477f24df2aa5"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.2.3-cp36-cp36m-macosx_10_11_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "688fd1eb6bd03135e7ff4af1c15b5949",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp36",
+ "requires_python": null,
+ "size": 110438,
+ "upload_time": "2017-06-19T00:39:10",
+ "url": "https://files.pythonhosted.org/packages/ae/6e/0ff15363cfc2691059207f5a50f4050603f03533cfa278957a6da1e247ab/pendulum-1.2.3-cp36-cp36m-macosx_10_11_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "c70d9eedcd4206f7df2f6e035b708039",
+ "sha256": "ad4257c4504dae8f031a5a487ad9ddcb92df5faa70a53c9d476b973ada6a572c"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.2.3-cp36-cp36m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "c70d9eedcd4206f7df2f6e035b708039",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp36",
+ "requires_python": null,
+ "size": 124314,
+ "upload_time": "2017-06-19T00:39:13",
+ "url": "https://files.pythonhosted.org/packages/db/ad/238c6c116d791ef0ce6aa893a84135971e893e19bd3b7316471836ad8168/pendulum-1.2.3-cp36-cp36m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "e6837a83ed804d2e0229111b87dd7fd8",
+ "sha256": "38f8fd2bd4f0b20e55fa828d09643c8a2b29d0dba7960cd6d0bf74bf2feb6b49"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.2.3-cp36-cp36m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "e6837a83ed804d2e0229111b87dd7fd8",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp36",
+ "requires_python": null,
+ "size": 124436,
+ "upload_time": "2017-06-19T00:39:15",
+ "url": "https://files.pythonhosted.org/packages/dd/6c/c69a8b69d413339992ab709ebd2f506b0a77136e66dcbe0655e55354ddeb/pendulum-1.2.3-cp36-cp36m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "2ea6798ef17fb1fb395e6a12ed56b5e2",
+ "sha256": "e5d056d371cb65355993c9fd439624945b6c50d5227dcbf57dcfab0845639c66"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.2.3.tar.gz",
+ "has_sig": false,
+ "md5_digest": "2ea6798ef17fb1fb395e6a12ed56b5e2",
+ "packagetype": "sdist",
+ "python_version": "source",
+ "requires_python": null,
+ "size": 69936,
+ "upload_time": "2017-06-19T00:39:17",
+ "url": "https://files.pythonhosted.org/packages/cb/8b/9dc4aba247a4357f6dfb1a0d21c03cfaf01f3aacde7cb5c478e4e9f418c6/pendulum-1.2.3.tar.gz"
+ }
+ ],
+ "1.2.4": [
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "1961af003d6f25e2e2944b38f56d3ec8",
+ "sha256": "e0c643dd3905968f5114dc0ffe151474edfbb717240f8f7e83867428b34fb7cd"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.2.4-cp27-cp27m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "1961af003d6f25e2e2944b38f56d3ec8",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": null,
+ "size": 124035,
+ "upload_time": "2017-06-20T20:04:09",
+ "url": "https://files.pythonhosted.org/packages/f2/fa/2c688716d411d017bf062078f2ffb4470f6750c1ceb430be54367a9df1b9/pendulum-1.2.4-cp27-cp27m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "c83158cced530604f7170198240b54cb",
+ "sha256": "377f97d24e60b2ca5e480d06a9576f36f8d7b0c51093973c2c8dbf3cca090e45"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.2.4-cp27-cp27m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "c83158cced530604f7170198240b54cb",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": null,
+ "size": 124212,
+ "upload_time": "2017-06-20T20:04:11",
+ "url": "https://files.pythonhosted.org/packages/4e/be/9a546c01048c18296ba91788e39915bb2667f00b1f1099a4b319b8cbb1b3/pendulum-1.2.4-cp27-cp27m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "cc4e8672b1e7496aa5d032e213a2658f",
+ "sha256": "5984f145cdf1cf52ef26c1aedc33a82b08532708f21d3ceb903d91ece8af6c48"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.2.4-cp35-cp35m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "cc4e8672b1e7496aa5d032e213a2658f",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": null,
+ "size": 124309,
+ "upload_time": "2017-06-20T20:04:14",
+ "url": "https://files.pythonhosted.org/packages/41/00/0db5c4aabfaa0f39398599e6e10b5bb3754dff68a4d14714dafafaa52812/pendulum-1.2.4-cp35-cp35m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "339849688cc909b1b0ee26896ad0820d",
+ "sha256": "b1478371102274c2415c3e51da31b402da1ad4488cd62aca561bf7947688eda4"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.2.4-cp35-cp35m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "339849688cc909b1b0ee26896ad0820d",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": null,
+ "size": 124436,
+ "upload_time": "2017-06-20T20:04:16",
+ "url": "https://files.pythonhosted.org/packages/43/d5/5f113d1b57784df2168d6931dc9f226a92173e13f79e474cc8527218a5da/pendulum-1.2.4-cp35-cp35m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "4c303eb7aa6de05f823b948b9a144957",
+ "sha256": "2bf697a0daf98fa66e476835819b079f00a498ad48f6e60a58c47399c500f8cd"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.2.4-cp36-cp36m-macosx_10_11_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "4c303eb7aa6de05f823b948b9a144957",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp36",
+ "requires_python": null,
+ "size": 110480,
+ "upload_time": "2017-06-20T20:04:18",
+ "url": "https://files.pythonhosted.org/packages/55/14/d70679c04596d2e9a35c1a3276e93768a280b12cbde86a3dccbb8ddaa054/pendulum-1.2.4-cp36-cp36m-macosx_10_11_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "a9ed93a56462de4a472c4e3849ad1565",
+ "sha256": "5ba233b4f3dfe45632410f3c7b45d0dc09a86b91e57a5b377d9f06a8db724d88"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.2.4-cp36-cp36m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "a9ed93a56462de4a472c4e3849ad1565",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp36",
+ "requires_python": null,
+ "size": 124358,
+ "upload_time": "2017-06-20T20:04:20",
+ "url": "https://files.pythonhosted.org/packages/0f/a9/0e07aefe92bf29eae8d474d5554de803724c13a96b085703194d754652a3/pendulum-1.2.4-cp36-cp36m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "5c5a05ab11bbdbd186d7da0a5ed6379b",
+ "sha256": "e2cb70778f2129c5dfefd6b0a13d75eb135618187bc0f77e665422ec578a86b5"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.2.4-cp36-cp36m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "5c5a05ab11bbdbd186d7da0a5ed6379b",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp36",
+ "requires_python": null,
+ "size": 124462,
+ "upload_time": "2017-06-20T20:04:23",
+ "url": "https://files.pythonhosted.org/packages/47/ae/6f5e3399e3d7208eb259b7ee39c0bdc41b001144b556c431f67412820c3e/pendulum-1.2.4-cp36-cp36m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "fccdff327f5d960d18cc49abae4c4c8f",
+ "sha256": "1f5554d329e870d114c7c83e30edf5ab1d43250edea2f621fb943811bb3743ba"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.2.4.tar.gz",
+ "has_sig": false,
+ "md5_digest": "fccdff327f5d960d18cc49abae4c4c8f",
+ "packagetype": "sdist",
+ "python_version": "source",
+ "requires_python": null,
+ "size": 69973,
+ "upload_time": "2017-06-20T20:04:25",
+ "url": "https://files.pythonhosted.org/packages/7a/73/e750347672bd4ec46fef02388a99031da456af26ed35f908cb53286622a1/pendulum-1.2.4.tar.gz"
+ }
+ ],
+ "1.2.5": [
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "3465eda1bb9b0c99f0fc6ac985f3520f",
+ "sha256": "8e24b9b6651402c9d5241cd09b2df16e8b8c2ee3e61ab0d243f7db81a7f4cc2b"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.2.5-cp27-cp27m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "3465eda1bb9b0c99f0fc6ac985f3520f",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": null,
+ "size": 124048,
+ "upload_time": "2017-09-04T12:27:39",
+ "url": "https://files.pythonhosted.org/packages/0d/b8/d60f6a2fd1dbfa7dc1fc299de75e145ff1f07cf36df1141c17ba91cbc84f/pendulum-1.2.5-cp27-cp27m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "d765971a4e63a2de66d0270541aeb832",
+ "sha256": "dfabd6ebf87ec050214bfa41debf0985a91f98a9f808787272c5ebb56bdf743a"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.2.5-cp27-cp27m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "d765971a4e63a2de66d0270541aeb832",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": null,
+ "size": 124231,
+ "upload_time": "2017-09-04T12:27:43",
+ "url": "https://files.pythonhosted.org/packages/12/c5/51f397c15a0cc6d5f29a9567335ee8d247b875d538de03cb4abb8887d936/pendulum-1.2.5-cp27-cp27m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "6cbf452de3f6cfffa783522a8fd9a777",
+ "sha256": "3415d9fb4d83e0a4466de24e2edcf385ce0378a5d9c06a4291d1d3411f5c9b4a"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.2.5-cp35-cp35m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "6cbf452de3f6cfffa783522a8fd9a777",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": null,
+ "size": 124328,
+ "upload_time": "2017-09-04T12:27:47",
+ "url": "https://files.pythonhosted.org/packages/b3/8e/cc6935e11015c01c289e1e5f82dfb46164ffae12ef2da733522ecd5532b8/pendulum-1.2.5-cp35-cp35m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "a437e6b71b7d86a1a018131df6fe43d6",
+ "sha256": "f47531a76ff67d21c2c0e1503c1bd8e5dbfd0ffb469c6ca8f68b6ef04ed7e8c4"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.2.5-cp35-cp35m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "a437e6b71b7d86a1a018131df6fe43d6",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": null,
+ "size": 124431,
+ "upload_time": "2017-09-04T12:27:52",
+ "url": "https://files.pythonhosted.org/packages/d2/d2/28c8c5b2c2fd77e9cc7064b3b398d14eef1d8ccbe33a39ba06a5f63c29f5/pendulum-1.2.5-cp35-cp35m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "550e853a28af0982c2e97d3a3d58acce",
+ "sha256": "8b52d8fc1e7a8b3025e434da351c98c34b478e8818d9fedbffed11ffb7a156cf"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.2.5-cp36-cp36m-macosx_10_11_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "550e853a28af0982c2e97d3a3d58acce",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp36",
+ "requires_python": null,
+ "size": 110532,
+ "upload_time": "2017-09-04T12:27:56",
+ "url": "https://files.pythonhosted.org/packages/9e/4b/2505c4e1eb8b849c76788d67c229b95f846f566535a6e8ae2e575e69ad3c/pendulum-1.2.5-cp36-cp36m-macosx_10_11_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "4c54c6c224710e6dcdd75dcd81ae6ebb",
+ "sha256": "878072ac65a2d2c9abc5954bb2eda305c7ec3b5430f39cb8819cc4b676dd79a3"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.2.5-cp36-cp36m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "4c54c6c224710e6dcdd75dcd81ae6ebb",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp36",
+ "requires_python": null,
+ "size": 124371,
+ "upload_time": "2017-09-04T12:28:00",
+ "url": "https://files.pythonhosted.org/packages/9c/96/085d6e6c55a4a01b910129d9df4b779b1e3af98d0c27bf5caf1483186a98/pendulum-1.2.5-cp36-cp36m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "28140a1825adfa8138a672abd2326ee4",
+ "sha256": "f00d45f5d4cc57829f778b024af35ce08ca0459993aff92d7606a14d7a872633"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.2.5-cp36-cp36m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "28140a1825adfa8138a672abd2326ee4",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp36",
+ "requires_python": null,
+ "size": 124483,
+ "upload_time": "2017-09-04T12:28:03",
+ "url": "https://files.pythonhosted.org/packages/ee/19/0d9e5205ed4adb7b7170ea7e31c57c39b4bab0b3c8d22c88d25bd665a33f/pendulum-1.2.5-cp36-cp36m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "27f2bde90d681d667d7a72807220dbc6",
+ "sha256": "1f9f4cba0b21beead709a38ea9847e4324f037052bbcfd93147634e9966aaba6"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.2.5.tar.gz",
+ "has_sig": false,
+ "md5_digest": "27f2bde90d681d667d7a72807220dbc6",
+ "packagetype": "sdist",
+ "python_version": "source",
+ "requires_python": null,
+ "size": 69938,
+ "upload_time": "2017-09-04T12:28:05",
+ "url": "https://files.pythonhosted.org/packages/69/d2/41b75edd6edcd296f9e8ab386b0847aed6005d4707cd072bfdadb9f3a995/pendulum-1.2.5.tar.gz"
+ }
+ ],
+ "1.3.0": [
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "7e929ad34ea2f0ef4d82b06b44a421d3",
+ "sha256": "f8dbd25920cb19de014a6cdd3401e00097a892779bff2c9ee86430d3c1c01afb"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.3.0-cp27-cp27m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "7e929ad34ea2f0ef4d82b06b44a421d3",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": null,
+ "size": 126196,
+ "upload_time": "2017-09-25T20:16:06",
+ "url": "https://files.pythonhosted.org/packages/55/86/12f8af49e7e882eb30f9080991938e38c6e471f102872979b3bdd403e910/pendulum-1.3.0-cp27-cp27m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "a9e82ec917e10edd3522170278c316cb",
+ "sha256": "3975c533fff06a5137facfd151ec4202192df89b4d5d2152d3c215f425452cd6"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.3.0-cp27-cp27m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "a9e82ec917e10edd3522170278c316cb",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": null,
+ "size": 126378,
+ "upload_time": "2017-09-25T20:16:10",
+ "url": "https://files.pythonhosted.org/packages/41/29/c95df766f1cf4887f2ba51a828545c521eb1e6596a1656c90f468b157a97/pendulum-1.3.0-cp27-cp27m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "285f9b47f3f406785f0402f4195d27aa",
+ "sha256": "e8b1f3a8b489815dd5fac150b532e1cf0bd6105b97b3b436bd12103cdbbd1eee"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.3.0-cp35-cp35m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "285f9b47f3f406785f0402f4195d27aa",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": null,
+ "size": 126495,
+ "upload_time": "2017-09-25T20:16:14",
+ "url": "https://files.pythonhosted.org/packages/1e/f9/b35921cd16dd8f65b1152e26f5b25408eb95ad788bfbd3b232134e506f7c/pendulum-1.3.0-cp35-cp35m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "4d3f3bb34b10abe868afa1233b65a8ba",
+ "sha256": "ea71a4a8f667a986aeb7621f6d240c81d16680e87df324a5aed6cb33e16e55ec"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.3.0-cp35-cp35m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "4d3f3bb34b10abe868afa1233b65a8ba",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": null,
+ "size": 126586,
+ "upload_time": "2017-09-25T20:16:18",
+ "url": "https://files.pythonhosted.org/packages/5f/d8/c500026ddb3a99289c1c2d7f22732c22380b30ea2901b45c1291dd6be373/pendulum-1.3.0-cp35-cp35m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "e9e4a7cfe3f4e0983655b6d7f5245236",
+ "sha256": "c74e0050016bc6640072df9db80f6a93c27bc126d6e0ac136e5ce4c7feefaaf1"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.3.0-cp36-cp36m-macosx_10_11_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "e9e4a7cfe3f4e0983655b6d7f5245236",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp36",
+ "requires_python": null,
+ "size": 112653,
+ "upload_time": "2017-09-25T20:16:22",
+ "url": "https://files.pythonhosted.org/packages/b5/a2/272212c99a41b83eaf40270c18ac6499dab679086abe558cb713c0dc55ef/pendulum-1.3.0-cp36-cp36m-macosx_10_11_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "8484655867cd7628273d42f06275826f",
+ "sha256": "3636d598e9df74fc4e2e025ea285177dabc57d073f9a69b2ded96c91b13474cc"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.3.0-cp36-cp36m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "8484655867cd7628273d42f06275826f",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp36",
+ "requires_python": null,
+ "size": 126527,
+ "upload_time": "2017-09-25T20:16:27",
+ "url": "https://files.pythonhosted.org/packages/cb/7e/3e892075a00a99ad5391a6ab648ae4277d6669c41f56e63f7cc96fed21a9/pendulum-1.3.0-cp36-cp36m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "df0e826d74fccba4d56886463a47c6b6",
+ "sha256": "a44313bd30ac5f5bdf08d441264c10229ef92c41948b071032b4fd26365a35f8"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.3.0-cp36-cp36m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "df0e826d74fccba4d56886463a47c6b6",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp36",
+ "requires_python": null,
+ "size": 126641,
+ "upload_time": "2017-09-25T20:16:31",
+ "url": "https://files.pythonhosted.org/packages/9a/9d/17a173ce8555e61c1ca79f5404c0f515d250eb638197b6fb6f1dbdb30c4f/pendulum-1.3.0-cp36-cp36m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "1f5f1ee6a64cfb4ca8fcf98fa24401df",
+ "sha256": "501d843c3679da48c6eee49b3cbd6e3e36017b34e4e7b6995ca16ad974d2c738"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.3.0.tar.gz",
+ "has_sig": false,
+ "md5_digest": "1f5f1ee6a64cfb4ca8fcf98fa24401df",
+ "packagetype": "sdist",
+ "python_version": "source",
+ "requires_python": null,
+ "size": 72029,
+ "upload_time": "2017-09-25T20:16:34",
+ "url": "https://files.pythonhosted.org/packages/7b/8c/0c2b32eaa82f00de332fe471eb1110732651ee22275339314b8469b869f7/pendulum-1.3.0.tar.gz"
+ }
+ ],
+ "1.3.1": [
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "eee9814391948a30943086af134c0b23",
+ "sha256": "80955d968c441d2d381d2b073dd445a6b027f791b36268442cdb624f85667b1c"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.3.1-cp27-cp27m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "eee9814391948a30943086af134c0b23",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": null,
+ "size": 126847,
+ "upload_time": "2017-10-22T21:08:44",
+ "url": "https://files.pythonhosted.org/packages/15/ff/2a269fc6fc952d849ef1104261151831cc80e3b895487932f882d9a5c90e/pendulum-1.3.1-cp27-cp27m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "99f78bc5b6d385e38adb4c8a025808b3",
+ "sha256": "9d5216a268278eac44e3e07ad823634d90add7bb93d9e460fd489f55f14f702f"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.3.1-cp27-cp27m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "99f78bc5b6d385e38adb4c8a025808b3",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": null,
+ "size": 127023,
+ "upload_time": "2017-10-22T21:08:50",
+ "url": "https://files.pythonhosted.org/packages/ba/b6/b3817535b0533728cfb3401c97152cff12d894f26ddb7fed029600462e50/pendulum-1.3.1-cp27-cp27m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "0e73bd45d716f7385aaaf7a01d5b5b4f",
+ "sha256": "f31cb65920b5754b603696a1bd4f922ee5be13500afb2bfa832fbf951c8348fc"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.3.1-cp35-cp35m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "0e73bd45d716f7385aaaf7a01d5b5b4f",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": null,
+ "size": 127104,
+ "upload_time": "2017-10-22T21:08:53",
+ "url": "https://files.pythonhosted.org/packages/07/56/493c131779e357c694248b55d5fccac6bbde7f3262aae9234f498cd276e5/pendulum-1.3.1-cp35-cp35m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "6b0a1188063550c53b14d2609f986962",
+ "sha256": "94add846ed1568ff43252c48b90760d7cfdc2a0da2167efb092942d50aa048e5"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.3.1-cp35-cp35m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "6b0a1188063550c53b14d2609f986962",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": null,
+ "size": 127259,
+ "upload_time": "2017-10-22T21:08:58",
+ "url": "https://files.pythonhosted.org/packages/d0/95/c738eef0c1708fdf1e7961dbad693102e88e7148d65382665f88e4175d76/pendulum-1.3.1-cp35-cp35m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "3b2f616590f25674bf80ac7613dc0971",
+ "sha256": "930b0765492f063bc10007039f865dd0acf3d91a70b350165a4e30fdba40cc93"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.3.1-cp36-cp36m-macosx_10_11_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "3b2f616590f25674bf80ac7613dc0971",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp36",
+ "requires_python": null,
+ "size": 113234,
+ "upload_time": "2017-10-22T21:09:01",
+ "url": "https://files.pythonhosted.org/packages/8e/ba/5f440952f827e232e8c38accba8dac3c4de97c5e71001a9e1d79766f51db/pendulum-1.3.1-cp36-cp36m-macosx_10_11_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "5d62b23ad4f99de868f0c40cfa9674ce",
+ "sha256": "6bfea234e03db8a0ad06f6ebbae4d43de7825ff1a7b63e67602e9bc5f26225eb"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.3.1-cp36-cp36m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "5d62b23ad4f99de868f0c40cfa9674ce",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp36",
+ "requires_python": null,
+ "size": 127153,
+ "upload_time": "2017-10-22T21:09:04",
+ "url": "https://files.pythonhosted.org/packages/3c/1f/c21e0a098fa6d34cd640c6cb06b2c8c17ba048bbb160ac85336f2f3471b8/pendulum-1.3.1-cp36-cp36m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "84228849c888af040f4095a6fd2e906c",
+ "sha256": "37cf099f2fabb62d5a069c91a29a2cb731fff5213abc682fd6364090e68a51d4"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.3.1-cp36-cp36m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "84228849c888af040f4095a6fd2e906c",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp36",
+ "requires_python": null,
+ "size": 127314,
+ "upload_time": "2017-10-22T21:09:21",
+ "url": "https://files.pythonhosted.org/packages/53/a5/31bda41c2e8acb90c55ec3fe5fe84b027a1297a5539423b4dd2ed5d60b4f/pendulum-1.3.1-cp36-cp36m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "e16e963bc2d077f7a1b1c9fc80ab2c9e",
+ "sha256": "f24e475e41cdbd43834e14652830cc0192d006ef0e8633b13c0e126d9a391d2f"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.3.1.tar.gz",
+ "has_sig": false,
+ "md5_digest": "e16e963bc2d077f7a1b1c9fc80ab2c9e",
+ "packagetype": "sdist",
+ "python_version": "source",
+ "requires_python": null,
+ "size": 74928,
+ "upload_time": "2017-10-22T21:09:29",
+ "url": "https://files.pythonhosted.org/packages/3b/71/bb2290b50f3f343f2842bfb6587ddd188ce98cf160fadecdcc9430565d45/pendulum-1.3.1.tar.gz"
+ }
+ ],
+ "1.3.2": [
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "a14edeba72b3c7a124f6bd824e29d1ff",
+ "sha256": "44ed222f2bcbbda64a4a9f7503bfbb7c539420f0a163a007c92cea9878d60dea"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.3.2-cp27-cp27m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "a14edeba72b3c7a124f6bd824e29d1ff",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": null,
+ "size": 128269,
+ "upload_time": "2017-11-16T20:20:11",
+ "url": "https://files.pythonhosted.org/packages/58/ba/64cc966085ac777e4a4a3d75a6b92cf9f74b62699f5cb54be5e195bd0aa7/pendulum-1.3.2-cp27-cp27m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "7bac437600d423fc94fc130fe6a95d60",
+ "sha256": "44361188a07f76a26dc1ea41fb20746723db17951d525617ae0db4a256d3ca32"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.3.2-cp27-cp27m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "7bac437600d423fc94fc130fe6a95d60",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": null,
+ "size": 128443,
+ "upload_time": "2017-11-16T20:20:14",
+ "url": "https://files.pythonhosted.org/packages/18/6b/53f9f74d46f05c7f29034cde8dcbfc43d02e62b60e87a66aadc17c116a24/pendulum-1.3.2-cp27-cp27m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "6ede358b89986c76fd93567478d3d092",
+ "sha256": "6eefa306dd3c9bf3ec6058fb7042877d0d7a12343925b67b62e6259a2541b899"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.3.2-cp35-cp35m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "6ede358b89986c76fd93567478d3d092",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": null,
+ "size": 128541,
+ "upload_time": "2017-11-16T20:20:17",
+ "url": "https://files.pythonhosted.org/packages/4c/48/82a8143df6f7a60d059b3ec09713f2d7878452916483ab18f111f395120d/pendulum-1.3.2-cp35-cp35m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "b6ad0e44d39f4314fd5e24fe2773f24d",
+ "sha256": "e2cad79f49134d743024f9d59b71224117d2712350cf601c6e93c8be84a1c82b"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.3.2-cp35-cp35m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "b6ad0e44d39f4314fd5e24fe2773f24d",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": null,
+ "size": 128683,
+ "upload_time": "2017-11-16T20:20:22",
+ "url": "https://files.pythonhosted.org/packages/ba/23/0817b0bcbd9775f7e204e67e2b17b1f45cdd7cda17b9d16bb90d37d9ae35/pendulum-1.3.2-cp35-cp35m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "56a462652b476ab308ef2c66a67c80c9",
+ "sha256": "aebffa08eefa3a4b9872dc1be87d5801a30604cde8dd7e25c9ec70ad2328e188"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.3.2-cp36-cp36m-macosx_10_11_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "56a462652b476ab308ef2c66a67c80c9",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp36",
+ "requires_python": null,
+ "size": 114661,
+ "upload_time": "2017-11-16T20:20:25",
+ "url": "https://files.pythonhosted.org/packages/ba/f7/d47f06d518430e52b66e8aa7fe6d5074054db25284f2d9f80fa3e631a55a/pendulum-1.3.2-cp36-cp36m-macosx_10_11_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "1ec79913850e581a261bc002c05bf450",
+ "sha256": "0bdeba610b66c4674764efa090088ce9a8bae780d8600e22ec55c4a4d01c01b5"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.3.2-cp36-cp36m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "1ec79913850e581a261bc002c05bf450",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp36",
+ "requires_python": null,
+ "size": 128581,
+ "upload_time": "2017-11-16T20:20:29",
+ "url": "https://files.pythonhosted.org/packages/26/e9/8fa3030aaba55d1c003c74d3e55383fedfe765d28137f16d9e46e3b52af9/pendulum-1.3.2-cp36-cp36m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "31f716c8517fce06abaa78d5cdfb826d",
+ "sha256": "beffaba5b2f5d22b1384062e4c4b0d6f710da225c8f43c1f03734c5e9d3bdfbb"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.3.2-cp36-cp36m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "31f716c8517fce06abaa78d5cdfb826d",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp36",
+ "requires_python": null,
+ "size": 128735,
+ "upload_time": "2017-11-16T20:20:33",
+ "url": "https://files.pythonhosted.org/packages/d1/a8/bf0bd1273e53a4fab5a403c7a02877ed17177bd236342727d9e86f57ff61/pendulum-1.3.2-cp36-cp36m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "f4da587566bf7b8a4f743ba2c59acbbe",
+ "sha256": "9284b53fd013dc4357644009b8d055a32c8bbbdf20fb95bc338d70089b6ed0c8"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.3.2.tar.gz",
+ "has_sig": false,
+ "md5_digest": "f4da587566bf7b8a4f743ba2c59acbbe",
+ "packagetype": "sdist",
+ "python_version": "source",
+ "requires_python": null,
+ "size": 75577,
+ "upload_time": "2017-11-16T20:20:36",
+ "url": "https://files.pythonhosted.org/packages/68/2e/f4243fd8360e7f7ba1ddc81794d04efeb76891bf994f981d68a4b521070b/pendulum-1.3.2.tar.gz"
+ }
+ ],
+ "1.4.0": [
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "9f9b966d73ee1dc486fb5ad15554e770",
+ "sha256": "9196f0aa4eec534aaf02b45c47dccc6f74a255ecdab6c772cb6bcea6b22790e4"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.4.0-cp27-cp27m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "9f9b966d73ee1dc486fb5ad15554e770",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": null,
+ "size": 127041,
+ "upload_time": "2018-01-22T16:01:06",
+ "url": "https://files.pythonhosted.org/packages/ae/4a/37ef677cfbfcf9320f241e1e061e4467de5de092941e2be053039ce30a09/pendulum-1.4.0-cp27-cp27m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "1c1ade36084490e4e5c8a83242f681cf",
+ "sha256": "a34690d8d4fc8eab34ea2dd9a99482dbbf0b1f059fe25effe204dd59bceda069"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.4.0-cp27-cp27m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "1c1ade36084490e4e5c8a83242f681cf",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": null,
+ "size": 127223,
+ "upload_time": "2018-01-22T16:01:07",
+ "url": "https://files.pythonhosted.org/packages/25/b6/481a191a3a43226b8fa2c1533e028414c99fb7f9232b0b99573a6ef184ca/pendulum-1.4.0-cp27-cp27m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "6b1d584d69997d5153ca42969fc3cfab",
+ "sha256": "1577a44b1f4bbc942136bce654df24e31735e1ff6aaa37e0a6207abf13868be9"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.4.0-cp35-cp35m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "6b1d584d69997d5153ca42969fc3cfab",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": null,
+ "size": 127305,
+ "upload_time": "2018-01-22T16:01:09",
+ "url": "https://files.pythonhosted.org/packages/70/81/52c3f6ed7ed398c1c13ac06b0db3fb4cef680c639b686b47b99d4ff6ea2e/pendulum-1.4.0-cp35-cp35m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "f0f818006201b9c8b0f8f306713bcff2",
+ "sha256": "f68f0f13498c9350ffc712765c4e0bdc824a4afd767d1a71933ff7be380bf75e"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.4.0-cp35-cp35m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "f0f818006201b9c8b0f8f306713bcff2",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": null,
+ "size": 127463,
+ "upload_time": "2018-01-22T16:01:10",
+ "url": "https://files.pythonhosted.org/packages/bd/8b/1afb7f5ab4d38efe6d25dc7e1cb0414be4acf2a3122f3d408bf9f924e565/pendulum-1.4.0-cp35-cp35m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "82ca9ea88f27e758b3bf0144342b7eb7",
+ "sha256": "76d6861664126fef4cbbdc6218ca09d81c4ed8da4c6df9637e0069f7d820f901"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.4.0-cp36-cp36m-macosx_10_13_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "82ca9ea88f27e758b3bf0144342b7eb7",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp36",
+ "requires_python": null,
+ "size": 113425,
+ "upload_time": "2018-01-22T16:01:12",
+ "url": "https://files.pythonhosted.org/packages/af/28/8f56db075fc77880f0a85aa49c2f5ae2ffdad8a5fc0c56d98ce0bfd84b95/pendulum-1.4.0-cp36-cp36m-macosx_10_13_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "0c86d5e6131ed13d154793306cfddaee",
+ "sha256": "327c89477e6ea0e240cd9f94c241747a534ac6f3e71c9b2f3298485ffc8939b2"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.4.0-cp36-cp36m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "0c86d5e6131ed13d154793306cfddaee",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp36",
+ "requires_python": null,
+ "size": 127354,
+ "upload_time": "2018-01-22T16:01:13",
+ "url": "https://files.pythonhosted.org/packages/dc/17/3b09897ff56d7cd148d75c06d407887bbc6f9f1b6c3609834b3175d5e802/pendulum-1.4.0-cp36-cp36m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "005b3f9815202f3955955c0d08f8bbc5",
+ "sha256": "4f1675010fd934aea011642c33c0dd9bc6954d9be7032c7f9ccfea1ac8d752d7"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.4.0-cp36-cp36m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "005b3f9815202f3955955c0d08f8bbc5",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp36",
+ "requires_python": null,
+ "size": 127520,
+ "upload_time": "2018-01-22T16:01:15",
+ "url": "https://files.pythonhosted.org/packages/37/89/b312f53c5c7295a9300b5853aa9a8ed61c6a91888c0744ef6b9ef11a21e5/pendulum-1.4.0-cp36-cp36m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "a22986bea611e14ef6510362728a9f0d",
+ "sha256": "e996c34fb101c9c6d88a839c19af74d7c067b92ed3371274efcf4d4b6dc160a6"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.4.0.tar.gz",
+ "has_sig": false,
+ "md5_digest": "a22986bea611e14ef6510362728a9f0d",
+ "packagetype": "sdist",
+ "python_version": "source",
+ "requires_python": null,
+ "size": 75021,
+ "upload_time": "2018-01-22T16:01:16",
+ "url": "https://files.pythonhosted.org/packages/bb/dc/02d70cedaa9e9042c05cae746e0543e67597cf5197872ebb92837cb2abee/pendulum-1.4.0.tar.gz"
+ }
+ ],
+ "1.4.1": [
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "c1ccbe36afa67d3875a28f7371da7fe5",
+ "sha256": "6340585b4df65b88732127601c7c8556fbcf7f0f9c7270a4afc0a8eb54e62343"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.4.1-cp27-cp27m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "c1ccbe36afa67d3875a28f7371da7fe5",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": null,
+ "size": 127032,
+ "upload_time": "2018-02-05T19:42:01",
+ "url": "https://files.pythonhosted.org/packages/70/20/b2fcb2e839b3ace43e3c73f581d6760b0323c08f8d32144d46604c87b7a3/pendulum-1.4.1-cp27-cp27m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "f5f718081f64010c8556e009cadf7dbd",
+ "sha256": "ef3a020ecd03cdad9ada397dd868e2c09348880df82e9b41628042e37235898a"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.4.1-cp27-cp27m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "f5f718081f64010c8556e009cadf7dbd",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": null,
+ "size": 127214,
+ "upload_time": "2018-02-05T19:42:04",
+ "url": "https://files.pythonhosted.org/packages/95/69/64103f6f3f2a363616f06bfa875f332fb3e286dbfa527f6ec2968c0026a1/pendulum-1.4.1-cp27-cp27m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "52d6486be9e3214c3930800db8d5ed86",
+ "sha256": "755bf25dfe4455af7c296751d10abe54ffcd17394c6005c16db9f84e71b1eacf"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.4.1-cp35-cp35m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "52d6486be9e3214c3930800db8d5ed86",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": null,
+ "size": 127296,
+ "upload_time": "2018-02-05T19:42:07",
+ "url": "https://files.pythonhosted.org/packages/a7/4c/d0fa68b9661451bd0e3a48316c5c92484ff8f7394e63001133b46b74195d/pendulum-1.4.1-cp35-cp35m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "0c1b9db96653f2f45474217d6c8a5f83",
+ "sha256": "dd8b9ebe9f00392f444cf963bed8d81efa59551ca1ccdf9f01837f0fbd52af5a"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.4.1-cp35-cp35m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "0c1b9db96653f2f45474217d6c8a5f83",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": null,
+ "size": 127448,
+ "upload_time": "2018-02-05T19:42:08",
+ "url": "https://files.pythonhosted.org/packages/28/64/c73eb81fac7af719a4689bb04ccb7261c7959501fe08008e1742feb11008/pendulum-1.4.1-cp35-cp35m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "66bbfeb1f68d17221afbb17b51762cc5",
+ "sha256": "bffaf9b8b333a3e64527a34bc5891e182b9dcd5811d2ff6fb68452fb771de5b2"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.4.1-cp36-cp36m-macosx_10_13_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "66bbfeb1f68d17221afbb17b51762cc5",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp36",
+ "requires_python": null,
+ "size": 113412,
+ "upload_time": "2018-02-05T19:42:11",
+ "url": "https://files.pythonhosted.org/packages/66/45/a0676a8124907424fafd9c85528e67cc0bdc9debc1b3055d6a0a39019dec/pendulum-1.4.1-cp36-cp36m-macosx_10_13_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "2503ef0b28dd8eed0032d9af14d6ec3a",
+ "sha256": "d7568452b7ab30a6d6ac15a4905455a924173d17e4801fac681a67c570e6d84e"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.4.1-cp36-cp36m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "2503ef0b28dd8eed0032d9af14d6ec3a",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp36",
+ "requires_python": null,
+ "size": 127338,
+ "upload_time": "2018-02-05T19:42:13",
+ "url": "https://files.pythonhosted.org/packages/5d/26/ed7ffcaa55cb2b289fad10dc1ad8b3bb0453cf3f3c397bddf5994b8a0689/pendulum-1.4.1-cp36-cp36m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "81f2e3dbce12ff0e44913b96fbb23dde",
+ "sha256": "ec71cea66eb8e0704e314ce693e8188d4f617e1ef84c3cd02fd11b688859062e"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.4.1-cp36-cp36m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "81f2e3dbce12ff0e44913b96fbb23dde",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp36",
+ "requires_python": null,
+ "size": 127501,
+ "upload_time": "2018-02-05T19:42:15",
+ "url": "https://files.pythonhosted.org/packages/88/8f/889dbf7bdb677861ba0f6a066c2415c3b3746a441f518685696205586f2d/pendulum-1.4.1-cp36-cp36m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "d54cc1e326098d9a284f876bc00cc13b",
+ "sha256": "3f16fb759e6126dd89d49886f8100caa72e5ab36563bc148b4f7eddfa0099c0f"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.4.1.tar.gz",
+ "has_sig": false,
+ "md5_digest": "d54cc1e326098d9a284f876bc00cc13b",
+ "packagetype": "sdist",
+ "python_version": "source",
+ "requires_python": null,
+ "size": 75020,
+ "upload_time": "2018-02-05T19:42:18",
+ "url": "https://files.pythonhosted.org/packages/d1/a7/71e2574d886b3f9bb227dbcdf5a89bbb20441d99381bc5db8659cd3e0536/pendulum-1.4.1.tar.gz"
+ }
+ ],
+ "1.4.2": [
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "00a4e6ea8d20c306888571607207b14d",
+ "sha256": "881efe37328de0785c0731d462e1485a45712f2cd5cb55907d6c15458460ebeb"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.4.2-cp27-cp27m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "00a4e6ea8d20c306888571607207b14d",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": null,
+ "size": 127074,
+ "upload_time": "2018-02-22T20:31:12",
+ "url": "https://files.pythonhosted.org/packages/92/5b/8fa2dd0be580a318a296ad0e87cb4234ed70c3c60394f9f8f005025af8a3/pendulum-1.4.2-cp27-cp27m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "f829c119914cee315d77ca639b016685",
+ "sha256": "3c85e8cbc91f45e1cc916cc9180b34153cd6aaaaacfb51a48b3156318314fa82"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.4.2-cp27-cp27m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "f829c119914cee315d77ca639b016685",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": null,
+ "size": 127250,
+ "upload_time": "2018-02-22T20:31:17",
+ "url": "https://files.pythonhosted.org/packages/c2/ff/de762a2994e51cd1333b705aa55a3006068b393aa56e9fb6b9deb1eea86d/pendulum-1.4.2-cp27-cp27m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "20a4566d7cebd37231a97d62fb336c21",
+ "sha256": "0c14388546db6605a860b8b7112cb69d0b11c9ce5e072210504544e0d4575799"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.4.2-cp35-cp35m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "20a4566d7cebd37231a97d62fb336c21",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": null,
+ "size": 127330,
+ "upload_time": "2018-02-22T20:31:19",
+ "url": "https://files.pythonhosted.org/packages/0e/45/0162e61268a9c996f396b68f2f15a6f901373a3e6e77a3e3f102fc5aa8b7/pendulum-1.4.2-cp35-cp35m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "989ce88d2fc32ec456fd27b4344833c2",
+ "sha256": "8798aeca58b3dd7ffdc5a4993c9eaafedc4048165429e8f499ddd62c73bf3964"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.4.2-cp35-cp35m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "989ce88d2fc32ec456fd27b4344833c2",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": null,
+ "size": 127487,
+ "upload_time": "2018-02-22T20:31:20",
+ "url": "https://files.pythonhosted.org/packages/e0/b9/c22bcff38e52f9c55d6fd416a66a51bb945a7ea10245e479157c60adb3d4/pendulum-1.4.2-cp35-cp35m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "a00c1d81899791f0e6a7f8585492afc9",
+ "sha256": "8199206c479b13947dcac63c025575d035331bb3819d1783dc1d568a11962906"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.4.2-cp36-cp36m-macosx_10_13_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "a00c1d81899791f0e6a7f8585492afc9",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp36",
+ "requires_python": null,
+ "size": 113453,
+ "upload_time": "2018-02-22T20:31:21",
+ "url": "https://files.pythonhosted.org/packages/2f/70/dd143c0e9077d6087fca0f7c71218bb1ea58f4e7ceb8562707a528cd4ef5/pendulum-1.4.2-cp36-cp36m-macosx_10_13_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "34102f4b8ed14475fc9e35b8cac7a1bf",
+ "sha256": "bcca072f82e84b419efec1320cd3ee5c230d263f3a601b146651ed4db77d89f0"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.4.2-cp36-cp36m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "34102f4b8ed14475fc9e35b8cac7a1bf",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp36",
+ "requires_python": null,
+ "size": 127384,
+ "upload_time": "2018-02-22T20:31:23",
+ "url": "https://files.pythonhosted.org/packages/9d/cd/b746dd8d57842c0bd38aa8bbbd8c92c9e24fee7b9f4c1d746a63b913f918/pendulum-1.4.2-cp36-cp36m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "df236d929186aa2efab8018a53ee061f",
+ "sha256": "ff0c5fa3af4a471a218408c448b804ac6bccb105127727474f4e83c0e4072e97"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.4.2-cp36-cp36m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "df236d929186aa2efab8018a53ee061f",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp36",
+ "requires_python": null,
+ "size": 127538,
+ "upload_time": "2018-02-22T20:31:25",
+ "url": "https://files.pythonhosted.org/packages/40/6d/17acccf0bef59b45bdafedf0d907f6c3b04b7352eb2f80788592edf62690/pendulum-1.4.2-cp36-cp36m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "ca17102ae2c14f73075e8b881fb4cbcd",
+ "sha256": "39a255776528afe11ea0d57814f9bf3729c1e0b99063af2e5c6cfd750c3e1f7f"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.4.2.tar.gz",
+ "has_sig": false,
+ "md5_digest": "ca17102ae2c14f73075e8b881fb4cbcd",
+ "packagetype": "sdist",
+ "python_version": "source",
+ "requires_python": null,
+ "size": 75074,
+ "upload_time": "2018-02-22T20:31:27",
+ "url": "https://files.pythonhosted.org/packages/df/34/219d94459b4dc1c33e0cd93af5fdabea19f9df3573fbaa4ae00eba0ad5bb/pendulum-1.4.2.tar.gz"
+ }
+ ],
+ "1.4.3": [
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "de2b591a80f890aa1ca7b193f353bcf0",
+ "sha256": "2497d9e2852e5401f6862416cfd99fad060f15437264da309e8bf68c17e95999"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.4.3-cp27-cp27m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "de2b591a80f890aa1ca7b193f353bcf0",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 123242,
+ "upload_time": "2018-03-20T23:53:00",
+ "url": "https://files.pythonhosted.org/packages/7b/21/dba7aa6829cae41139313977dcdf19c70cc98882a64f712eef5a358e16df/pendulum-1.4.3-cp27-cp27m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "df425ee565f312a40005b046a3c3440b",
+ "sha256": "1d2d317aeb17adab5bec3f33facd6971c89ae0d42834dd25fb3d3578bcef9129"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.4.3-cp27-cp27m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "df425ee565f312a40005b046a3c3440b",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 123420,
+ "upload_time": "2018-03-20T23:52:50",
+ "url": "https://files.pythonhosted.org/packages/80/02/9bfae1e3a46fe957095385453314bbb25906f06b0425ffd87099edfdae22/pendulum-1.4.3-cp27-cp27m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "99d1dc914f88aa4f6a78373217cffcd8",
+ "sha256": "bd17f5876d8bc2637df4ecb6722fdfb7ae84021a35bd83a39bf252f74b13d3aa"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.4.3-cp35-cp35m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "99d1dc914f88aa4f6a78373217cffcd8",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 123506,
+ "upload_time": "2018-03-20T23:52:59",
+ "url": "https://files.pythonhosted.org/packages/cb/fc/71ece5a0c31ba48fd3b3527c122e7117bc4b10b8a25f5bb90de2807c21b0/pendulum-1.4.3-cp35-cp35m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "88ab7566cd6a93aa3d20a44a117dfc13",
+ "sha256": "25b853fe2fc204e471474762ddf2481ad018044e1f294457ff3e769227be986c"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.4.3-cp35-cp35m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "88ab7566cd6a93aa3d20a44a117dfc13",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 123658,
+ "upload_time": "2018-03-20T23:52:53",
+ "url": "https://files.pythonhosted.org/packages/24/d5/25509aceed45a9ab73a77b7683108cdc8559499fa035073b1aebc159f48f/pendulum-1.4.3-cp35-cp35m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "2a6d03c1008b6a20fd9ef8dc5e14fae3",
+ "sha256": "d9da591b2ad233321c8d8d1ea7acfaca6c36f4e0503a4043967ce8750c6e33ac"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.4.3-cp36-cp36m-macosx_10_13_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "2a6d03c1008b6a20fd9ef8dc5e14fae3",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp36",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 383885,
+ "upload_time": "2018-03-20T23:52:57",
+ "url": "https://files.pythonhosted.org/packages/fc/3b/d20dc4dce8a2f22ebf305099b53ca318eda2d713fc2b6c80419efc0ac0d0/pendulum-1.4.3-cp36-cp36m-macosx_10_13_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "b1948a25f18729d916d86e883d2339c0",
+ "sha256": "ad33231155b4013c9f838c157fc79975e3739ee028d8b9291d2abb48b4ab5996"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.4.3-cp36-cp36m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "b1948a25f18729d916d86e883d2339c0",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp36",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 123537,
+ "upload_time": "2018-03-20T23:52:54",
+ "url": "https://files.pythonhosted.org/packages/52/db/6b723f7eeeb14bc6f062a5e9c9b42732fa62be49fdbdb1ff5b32b174250b/pendulum-1.4.3-cp36-cp36m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "f93336e7c67c36baa5e67a9811ee25d1",
+ "sha256": "a20d6d86c2302fd3afed5979417ff2eeb4d3a752f462ec3fc38fbf40a782ecbb"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.4.3-cp36-cp36m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "f93336e7c67c36baa5e67a9811ee25d1",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp36",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 123706,
+ "upload_time": "2018-03-20T23:52:51",
+ "url": "https://files.pythonhosted.org/packages/49/80/80e8b89cc43f13f2e7e69b187a3afdffae603c7b91c40284c2ea2ab453b7/pendulum-1.4.3-cp36-cp36m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "c5ccb9a686feda5a6089d01fae9cacca",
+ "sha256": "8a5ed77dde59f4a6bc82e4ba4fa3d4071e8002406d04ff26ca42e4ad9d7b5191"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.4.3.tar.gz",
+ "has_sig": false,
+ "md5_digest": "c5ccb9a686feda5a6089d01fae9cacca",
+ "packagetype": "sdist",
+ "python_version": "source",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 74984,
+ "upload_time": "2018-03-20T23:52:55",
+ "url": "https://files.pythonhosted.org/packages/b8/40/828bf56af477fb85618126ad8162b7cf5bed84c28a94bfa42f72ad42010c/pendulum-1.4.3.tar.gz"
+ }
+ ],
+ "1.4.4": [
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "490eaf9e3cc60c261ea00d9087547efe",
+ "sha256": "501670f3b1d581395ec4094aff7c13dca6b699d1810cf15c446433b9e736eb4a"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.4.4-cp27-cp27m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "490eaf9e3cc60c261ea00d9087547efe",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 123240,
+ "upload_time": "2018-03-21T06:54:49",
+ "url": "https://files.pythonhosted.org/packages/3b/d2/99d1ad74abb8feab462ed065f35f694bf4b6465052a84b0007269371895d/pendulum-1.4.4-cp27-cp27m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "3b8ea5304556af34be7683ecaf913c37",
+ "sha256": "b9a7ef02ad6255292f35218c595f8be35e0ca3c7ac19e633ff2de96480f26ab3"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.4.4-cp27-cp27m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "3b8ea5304556af34be7683ecaf913c37",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 123418,
+ "upload_time": "2018-03-21T06:54:43",
+ "url": "https://files.pythonhosted.org/packages/87/9f/8d1dc7789430b746b671533297ed633c44af05b33da8d395389afb27f9e8/pendulum-1.4.4-cp27-cp27m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "f4b3b3d3cbab82b0bf379f4fe16be120",
+ "sha256": "3d8b280a903fb25bdba258203bbcd0533c5c04a65878f6e0700931dedd2bae72"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.4.4-cp35-cp35m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "f4b3b3d3cbab82b0bf379f4fe16be120",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 123503,
+ "upload_time": "2018-03-21T06:54:48",
+ "url": "https://files.pythonhosted.org/packages/cb/7d/37a9b89c3bfbceafe083f52e5d783a39e79b4d7998f133bfbeee94830858/pendulum-1.4.4-cp35-cp35m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "206497d3fc5fe4400aea9cda44c3b217",
+ "sha256": "f30fb1149e4f67b3aaa9eae874dca7bbf49788ac121d702486f5b9fe549e7920"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.4.4-cp35-cp35m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "206497d3fc5fe4400aea9cda44c3b217",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 123663,
+ "upload_time": "2018-03-21T06:54:51",
+ "url": "https://files.pythonhosted.org/packages/cc/ba/a7ef16485be134f0acec118b6b9036741d664cc0042c7d6e48c613ea9d88/pendulum-1.4.4-cp35-cp35m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "adc05b64c3cc76f9a9c067b1fe86f43a",
+ "sha256": "4c945ed6a3b0afab8c2f1b1e3e26bb23ad0a9be6f201604111a8217cea78e7ab"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.4.4-cp36-cp36m-macosx_10_13_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "adc05b64c3cc76f9a9c067b1fe86f43a",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp36",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 383887,
+ "upload_time": "2018-03-21T06:54:46",
+ "url": "https://files.pythonhosted.org/packages/05/20/2b6261cadc4d71f6c08bd0986732acbe474c08d97194a6bfc025bff10a05/pendulum-1.4.4-cp36-cp36m-macosx_10_13_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "d4f2dfb526363b38a62f722cc5923f80",
+ "sha256": "253983de6d64a01909c2524e4ab27febd0d3987d001ea6ab93a7b945fdc0e6c6"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.4.4-cp36-cp36m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "d4f2dfb526363b38a62f722cc5923f80",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp36",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 123547,
+ "upload_time": "2018-03-21T06:54:53",
+ "url": "https://files.pythonhosted.org/packages/69/10/24d5376a9d1604766196c3ddd13be1c1616ad0eeee31bf127b32cdcdd587/pendulum-1.4.4-cp36-cp36m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "6a197496340b96348b25a48a0d873b10",
+ "sha256": "76ee830b4b57a3f8244a228505bf9c55285cc92f1a200c8578b0ca54f8185861"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.4.4-cp36-cp36m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "6a197496340b96348b25a48a0d873b10",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp36",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 123707,
+ "upload_time": "2018-03-21T06:54:42",
+ "url": "https://files.pythonhosted.org/packages/30/47/02f04abed54918d2a3f1da602a8254247670b2e1a99b4b1f02734a27e71e/pendulum-1.4.4-cp36-cp36m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "85ff49b389e0d251efdd95f2b8638810",
+ "sha256": "601e52cb0425e94b1784b6613a9085e0066ae1fa1915d18771884b67e93cac5c"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.4.4.tar.gz",
+ "has_sig": false,
+ "md5_digest": "85ff49b389e0d251efdd95f2b8638810",
+ "packagetype": "sdist",
+ "python_version": "source",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 74994,
+ "upload_time": "2018-03-21T06:54:45",
+ "url": "https://files.pythonhosted.org/packages/85/a5/9fc15751f9725923b170ad37d6c61031fc9e941bafd5288ca6ee51233284/pendulum-1.4.4.tar.gz"
+ }
+ ],
+ "1.5.0": [
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "77b205ab331c3b50894a1a11a3a1aae8",
+ "sha256": "de327b5b1567dc19ddb0b8b0e2c50170b61d743e2d3c9b5884f458b7a81ac137"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.5.0-cp27-cp27m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "77b205ab331c3b50894a1a11a3a1aae8",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 124407,
+ "upload_time": "2018-04-16T22:49:45",
+ "url": "https://files.pythonhosted.org/packages/16/6f/f74f8d5f22cbfee181de108f700f90b1bc593a2d619f192bbbe584d600a7/pendulum-1.5.0-cp27-cp27m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "786aac929ca03996d4caa7efc3df95c8",
+ "sha256": "68c193cb63ac065f403f1be7ce8c89bf30f08adeb263a733435e69e30b86faf9"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.5.0-cp27-cp27m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "786aac929ca03996d4caa7efc3df95c8",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 124592,
+ "upload_time": "2018-04-16T22:49:39",
+ "url": "https://files.pythonhosted.org/packages/09/b3/0a37d24e23f7767870b91a9d9178b9c0fedca65496a92e9ec72a6a5dddb7/pendulum-1.5.0-cp27-cp27m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "ef4953063729b5be97170618d1ceb2fc",
+ "sha256": "a6138aab0e7a983ca40e5349735ca86a72e710e5c74bc3ebb03d3ade83df6a89"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.5.0-cp34-cp34m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "ef4953063729b5be97170618d1ceb2fc",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp34",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 124494,
+ "upload_time": "2018-04-16T22:49:37",
+ "url": "https://files.pythonhosted.org/packages/67/45/c7a99745e4852828dbca1d1c064aa86f8801772580e6f57458711845f55b/pendulum-1.5.0-cp34-cp34m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "cf40b04aa13efb24d8dfd696fc21e5ea",
+ "sha256": "d1fdc005c6513ad85141c6f30a719b79bf2a85599ab0b8b40955bf8f103c9c33"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.5.0-cp34-cp34m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "cf40b04aa13efb24d8dfd696fc21e5ea",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp34",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 124643,
+ "upload_time": "2018-04-16T22:49:47",
+ "url": "https://files.pythonhosted.org/packages/89/d3/88343c957c7f6d57858450ca463b19f6faecb16f3332f9531eea5adbc7f7/pendulum-1.5.0-cp34-cp34m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "1d96901787941182c783c7cd34b866ef",
+ "sha256": "b05cabedbd434f0848981ac5bf405ed03d6586be64185c50ac94cb1bc3398a85"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.5.0-cp35-cp35m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "1d96901787941182c783c7cd34b866ef",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 124665,
+ "upload_time": "2018-04-16T22:49:44",
+ "url": "https://files.pythonhosted.org/packages/41/fb/fc75737de23c7205131f5e87446ed4b8111068a56ea3600b04dcc841cd0d/pendulum-1.5.0-cp35-cp35m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "8f6edb69a23272da49e2b8d99794abb8",
+ "sha256": "70ba2cf4c9acee0e6b0d9d32f21b0d8a5d12b9d759c7e289982c775159027897"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.5.0-cp35-cp35m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "8f6edb69a23272da49e2b8d99794abb8",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 124835,
+ "upload_time": "2018-04-16T22:49:42",
+ "url": "https://files.pythonhosted.org/packages/8f/48/8690766bd5f7da046e30f061006ffdd81c6a5ce4536a8dfd6a154bae209a/pendulum-1.5.0-cp35-cp35m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "71ae9a9a659c7088b82c72eb3cd50c53",
+ "sha256": "ccfad31f7f2c8eabe0a791f196b27119ce53bc2c6d0cc73230413bc25ea057df"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.5.0-cp36-cp36m-macosx_10_13_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "71ae9a9a659c7088b82c72eb3cd50c53",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp36",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 395631,
+ "upload_time": "2018-04-16T22:49:38",
+ "url": "https://files.pythonhosted.org/packages/58/6d/db20859c9cf2049ffee9f47055ec378fbff62a98443762e5d4d841aaf58f/pendulum-1.5.0-cp36-cp36m-macosx_10_13_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "0a7348b86bbba517f2e425d90bb4b284",
+ "sha256": "3f9f1927582fc2b850a07163ecac86da89e5a26ddf86ef4b41ac502bb3f17428"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.5.0-cp36-cp36m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "0a7348b86bbba517f2e425d90bb4b284",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp36",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 124717,
+ "upload_time": "2018-04-16T22:49:48",
+ "url": "https://files.pythonhosted.org/packages/ac/f2/9d50542fea2e8690405869ba84e42562ef4c259a9f0220241ac2a12ed7d8/pendulum-1.5.0-cp36-cp36m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "9b6a6b19dd1bf0697e17fb32f5513c9c",
+ "sha256": "bea008b210f8b4ed7a62315a76e7e4d721f572b183d470486f4cf995a690be3f"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.5.0-cp36-cp36m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "9b6a6b19dd1bf0697e17fb32f5513c9c",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp36",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 124888,
+ "upload_time": "2018-04-16T22:49:41",
+ "url": "https://files.pythonhosted.org/packages/10/27/cbf88a47b3ae973ed3c0da1b754bcd3f7c0e366e1853adf2d22535aab3e2/pendulum-1.5.0-cp36-cp36m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "0b32710dbe5245d8c88e76888d5daafe",
+ "sha256": "395bfe54a737ec6a4a95e5850753dddefe52bd54461de896afc4ce2ac91d4b78"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.5.0.tar.gz",
+ "has_sig": false,
+ "md5_digest": "0b32710dbe5245d8c88e76888d5daafe",
+ "packagetype": "sdist",
+ "python_version": "source",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 75993,
+ "upload_time": "2018-04-16T22:49:35",
+ "url": "https://files.pythonhosted.org/packages/09/22/d0b261955291f40c0981e002c5f153cb603a169023157f1ce9ea3925f69e/pendulum-1.5.0.tar.gz"
+ }
+ ],
+ "1.5.1": [
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "37c25a5ec3636177bf4a9dc2dca46cba",
+ "sha256": "ddaf97a061eb5e2ae37857a8cb548e074125017855690d20e443ad8d9f31e164"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.5.1-cp27-cp27m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "37c25a5ec3636177bf4a9dc2dca46cba",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 124445,
+ "upload_time": "2018-04-25T00:04:05",
+ "url": "https://files.pythonhosted.org/packages/f0/11/20ba4cfe1e5382b5e6aebd68b3da0c6d097d121fb8527c4f9f5fdde01b33/pendulum-1.5.1-cp27-cp27m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "4903bbc8da3222630da92974d7f60eb1",
+ "sha256": "c04fcf955e622e97e405e5f6d1b1f4a7adc69d79d82f3609643de69283170d6d"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.5.1-cp27-cp27m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "4903bbc8da3222630da92974d7f60eb1",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 124617,
+ "upload_time": "2018-04-25T00:04:02",
+ "url": "https://files.pythonhosted.org/packages/1a/fb/86dae40d7da8fe906fe9ff1dc6948bc2440403405b1c695c74cb094799c4/pendulum-1.5.1-cp27-cp27m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "608b41b5f6d2304de7ddab23bfdd2e56",
+ "sha256": "dd6500d27bb7ccc029d497da4f9bd09549bd3c0ea276dad894ea2fdf309e83f3"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.5.1-cp34-cp34m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "608b41b5f6d2304de7ddab23bfdd2e56",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp34",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 124518,
+ "upload_time": "2018-04-25T00:03:58",
+ "url": "https://files.pythonhosted.org/packages/37/fd/470aeabaa27f4a26632db87e6d19c390d0c65c5c8b3859a09a9627293880/pendulum-1.5.1-cp34-cp34m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "432119510012714d062bbb5e9b648ead",
+ "sha256": "95536b33ae152e3c831eb236c1bf9ac9dcfb3b5b98fdbe8e9e601eab6c373897"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.5.1-cp34-cp34m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "432119510012714d062bbb5e9b648ead",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp34",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 124674,
+ "upload_time": "2018-04-25T00:03:55",
+ "url": "https://files.pythonhosted.org/packages/c4/74/74e3dfedaebdfd808ed23b7552deafe7c0abb117472e91c8fc523693ea0c/pendulum-1.5.1-cp34-cp34m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "0b5dc205fb654e2b89b3a4d91bdd10f8",
+ "sha256": "f4eee1e1735487d9d25cc435c519fd4380cb1f82cde3ebad1efbc2fc30deca5b"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.5.1-cp35-cp35m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "0b5dc205fb654e2b89b3a4d91bdd10f8",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 124699,
+ "upload_time": "2018-04-25T00:04:04",
+ "url": "https://files.pythonhosted.org/packages/4b/1b/ff9817d14a5fbf36dd35ad2b2867a65258abe43ea82f474961f85a726c26/pendulum-1.5.1-cp35-cp35m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "f236b2ebb9aad82cac2a9d7d824a4f5e",
+ "sha256": "4173ce3e81ad0d9d61dbce86f4286c43a26a398270df6a0a89f501f0c28ad27d"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.5.1-cp35-cp35m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "f236b2ebb9aad82cac2a9d7d824a4f5e",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 124865,
+ "upload_time": "2018-04-25T00:03:57",
+ "url": "https://files.pythonhosted.org/packages/72/dc/89a21999a3496e39618cc7a1005dfcdf5ccd1876460127c2c5def15afd16/pendulum-1.5.1-cp35-cp35m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "feb6a2fdd70d0fdbc071d9e79012702b",
+ "sha256": "e9732b8bb214fad2c72ddcbfec07542effa8a8b704e174347ede1ff8dc679cce"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.5.1-cp36-cp36m-macosx_10_13_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "feb6a2fdd70d0fdbc071d9e79012702b",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp36",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 395755,
+ "upload_time": "2018-04-25T00:04:00",
+ "url": "https://files.pythonhosted.org/packages/4e/43/ccc5c72872b08dfbd155e4c53834f9c333af943fd4e5705e1756480cfdfe/pendulum-1.5.1-cp36-cp36m-macosx_10_13_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "120f499dd4f433ad593d4ac81b7a7c90",
+ "sha256": "56a347d0457859c84b8cdba161fc37c7df5db9b3becec7881cd770e9d2058b3c"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.5.1-cp36-cp36m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "120f499dd4f433ad593d4ac81b7a7c90",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp36",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 124741,
+ "upload_time": "2018-04-25T00:04:03",
+ "url": "https://files.pythonhosted.org/packages/23/7a/99520e2857fb1d8acbb0def0cf524a22b066f230b47d6547d7d955947f7f/pendulum-1.5.1-cp36-cp36m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "4d416f46008dac96d04ad93b9f3cf233",
+ "sha256": "e7df37447824f9af0b58c7915a4caf349926036afd86ad38e7529a6b2f8fc34b"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.5.1-cp36-cp36m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "4d416f46008dac96d04ad93b9f3cf233",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp36",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 124916,
+ "upload_time": "2018-04-25T00:04:07",
+ "url": "https://files.pythonhosted.org/packages/a6/1b/95589c9e276fa7e624d3e07020ffee8b200d6d263fd141eb1f2ad0767aa7/pendulum-1.5.1-cp36-cp36m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "393396012adad72ecbca36e595742b63",
+ "sha256": "738878168eb26e5446da5d1f7b3312ae993a542061be8882099c00ef4866b1a2"
+ },
+ "downloads": -1,
+ "filename": "pendulum-1.5.1.tar.gz",
+ "has_sig": false,
+ "md5_digest": "393396012adad72ecbca36e595742b63",
+ "packagetype": "sdist",
+ "python_version": "source",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 76100,
+ "upload_time": "2018-04-25T00:04:01",
+ "url": "https://files.pythonhosted.org/packages/ca/a5/0f9fe22bae01ba13b823a38da280dc5823f739ff68d8e130def665655925/pendulum-1.5.1.tar.gz"
+ }
+ ],
+ "2.0.0": [
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "bd0a295dee4d23f4bf4477ddcfb590a5",
+ "sha256": "6a0d65d3a7632e6eeaf2f34401dcec3d56c87f5eb8f6d66b76a1bddf3cef66cc"
+ },
+ "downloads": -1,
+ "filename": "pendulum-2.0.0-cp27-cp27m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "bd0a295dee4d23f4bf4477ddcfb590a5",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 92728,
+ "upload_time": "2018-05-08T20:10:38",
+ "url": "https://files.pythonhosted.org/packages/2c/65/2b1abf6a6789e8fe5a905d69b99a517a120c04f217eb0358481dc29e63dc/pendulum-2.0.0-cp27-cp27m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "5caaa1c280e7b15cb7e31a027ec367e0",
+ "sha256": "4a1097f87aa8ea84a5a15f2a8f812bda7df7d082c8926555a804fa31618ba9b9"
+ },
+ "downloads": -1,
+ "filename": "pendulum-2.0.0-cp27-cp27m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "5caaa1c280e7b15cb7e31a027ec367e0",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 92731,
+ "upload_time": "2018-05-08T20:10:27",
+ "url": "https://files.pythonhosted.org/packages/8d/4e/311d56caefa8fc8f9f747870c331cc2528759048964f50deb4b3c88558da/pendulum-2.0.0-cp27-cp27m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "054ba6f739049920f499a2d7bb9aae95",
+ "sha256": "db3192df663c10ec4a30bedef855ecfbf84b8f890a1abfdb137e890c9cf2d72c"
+ },
+ "downloads": -1,
+ "filename": "pendulum-2.0.0-cp34-cp34m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "054ba6f739049920f499a2d7bb9aae95",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp34",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 135997,
+ "upload_time": "2018-05-08T20:10:29",
+ "url": "https://files.pythonhosted.org/packages/96/ec/9ecdebe38533fa336ec4a1996a9d84654fb64e0676b5a9fd2f5efffc1034/pendulum-2.0.0-cp34-cp34m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "683a59c12de73a70c8ecdaefcb4d2588",
+ "sha256": "c1fbac0e8077658aa83e0d56d2c77b3578f11c7c88d9984bf1c1efee8b2f109c"
+ },
+ "downloads": -1,
+ "filename": "pendulum-2.0.0-cp34-cp34m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "683a59c12de73a70c8ecdaefcb4d2588",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp34",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 136637,
+ "upload_time": "2018-05-08T20:10:31",
+ "url": "https://files.pythonhosted.org/packages/bd/8e/c336fac02e57149fae05d16a192f6b264e4f7b6f30360820cda2afe98004/pendulum-2.0.0-cp34-cp34m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "b6fc855ffcf9f0290ad182e580bc8ef0",
+ "sha256": "2c926f76ff9dab4f80e0cb2f03351241dfcbaaa898d6670a647d67d52792e7df"
+ },
+ "downloads": -1,
+ "filename": "pendulum-2.0.0-cp35-cp35m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "b6fc855ffcf9f0290ad182e580bc8ef0",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 136345,
+ "upload_time": "2018-05-08T20:10:37",
+ "url": "https://files.pythonhosted.org/packages/17/0e/f3228a74a1828e06b1e0feb6f9e3c5389cf6cb0464416fb37e970c9afb5d/pendulum-2.0.0-cp35-cp35m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "ec6cda9833d58a20eed01fa37e7e6acf",
+ "sha256": "107eb0a59f8ce5b15d1aaae9e4ab796f3ec12c46f25a251bca64cc6620ebfa86"
+ },
+ "downloads": -1,
+ "filename": "pendulum-2.0.0-cp35-cp35m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "ec6cda9833d58a20eed01fa37e7e6acf",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 137015,
+ "upload_time": "2018-05-08T20:10:34",
+ "url": "https://files.pythonhosted.org/packages/87/ab/bf7ebe3ab1113a8114a731bd2d5913e1068719ecf7455b6fdb4fb546b458/pendulum-2.0.0-cp35-cp35m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "15ccf84fc578813169a5c07b3b7674ae",
+ "sha256": "4c6b4f809c2283c661500527520314d213df61d85eadd93bc1f4f5abc886b4e5"
+ },
+ "downloads": -1,
+ "filename": "pendulum-2.0.0-cp36-cp36m-macosx_10_13_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "15ccf84fc578813169a5c07b3b7674ae",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp36",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 415118,
+ "upload_time": "2018-05-08T20:10:35",
+ "url": "https://files.pythonhosted.org/packages/1e/90/a2a71d03aa94c1fba28de507d8dbd429d3ac8483d1e9cf5a031861f7b691/pendulum-2.0.0-cp36-cp36m-macosx_10_13_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "ac5ea8f693c647e539c66abf92fbdfa7",
+ "sha256": "4e32446d39623b17e7a3aa8d8b190dc173883220f3a0dc18158c29038b731261"
+ },
+ "downloads": -1,
+ "filename": "pendulum-2.0.0-cp36-cp36m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "ac5ea8f693c647e539c66abf92fbdfa7",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp36",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 136468,
+ "upload_time": "2018-05-08T20:10:32",
+ "url": "https://files.pythonhosted.org/packages/8e/e0/a416abdfda75d53faec074b229afbf3f7e78fe26f395281419673404e390/pendulum-2.0.0-cp36-cp36m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "288efe992308f29924834badc25e2e77",
+ "sha256": "4e420a8e10a44c7a29bb27d73bdf32f3a4957f77e63242483064e2f9acadbdd7"
+ },
+ "downloads": -1,
+ "filename": "pendulum-2.0.0-cp36-cp36m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "288efe992308f29924834badc25e2e77",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp36",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 137166,
+ "upload_time": "2018-05-08T20:10:30",
+ "url": "https://files.pythonhosted.org/packages/78/dc/c74243f2b463ef63e7390fdeccb7d5bbc370da05678bd57ca2271e9e168d/pendulum-2.0.0-cp36-cp36m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "c64622797dea8a83554a137fe1913bad",
+ "sha256": "4eb01d8a47dc7d2184886491aac43999ba7671a9418f56eb761b53d8480995f2"
+ },
+ "downloads": -1,
+ "filename": "pendulum-2.0.0.tar.gz",
+ "has_sig": false,
+ "md5_digest": "c64622797dea8a83554a137fe1913bad",
+ "packagetype": "sdist",
+ "python_version": "source",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 74321,
+ "upload_time": "2018-05-08T20:10:28",
+ "url": "https://files.pythonhosted.org/packages/6e/83/61239409b111fd0832d5572b1d87d9589c77f17ec609651f8b5f1b8ffb61/pendulum-2.0.0.tar.gz"
+ }
+ ],
+ "2.0.0a0": [
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "c90785522d79abea90e9adcf9e6b6b6b",
+ "sha256": "234a41e9915e1a1fd7a24c8f6c634ed0b823783521aafe02da171c9b8c921eca"
+ },
+ "downloads": -1,
+ "filename": "pendulum-2.0.0a0-cp27-cp27m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "c90785522d79abea90e9adcf9e6b6b6b",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 89725,
+ "upload_time": "2018-04-16T22:31:57",
+ "url": "https://files.pythonhosted.org/packages/b7/e7/986886a9498e915f38ad8de115bef9b20fa5e2a457cbae69d86dc4087731/pendulum-2.0.0a0-cp27-cp27m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "fe13ab0d60940306a879236882b9370a",
+ "sha256": "77147be7adf19905b5a85ac7fedfaa2616b0970697448b806e099b0fb1c07511"
+ },
+ "downloads": -1,
+ "filename": "pendulum-2.0.0a0-cp27-cp27m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "fe13ab0d60940306a879236882b9370a",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 89730,
+ "upload_time": "2018-04-16T22:31:52",
+ "url": "https://files.pythonhosted.org/packages/c0/14/0134a36f34592520f25daffbc58deb7bee9a902b415b40d5c9a0d709c0b3/pendulum-2.0.0a0-cp27-cp27m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "5a14d4677f6b07e7c6a7cc15877a0c7a",
+ "sha256": "cbf98b4d70112819ecce02868491a2f196408b6e2b6010667905ab439c30907a"
+ },
+ "downloads": -1,
+ "filename": "pendulum-2.0.0a0-cp34-cp34m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "5a14d4677f6b07e7c6a7cc15877a0c7a",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp34",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 132991,
+ "upload_time": "2018-04-16T22:32:04",
+ "url": "https://files.pythonhosted.org/packages/3b/76/e27aaa207b244c5deea3d687297c2f2469ddd0b695735cfbd7ebb17da679/pendulum-2.0.0a0-cp34-cp34m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "b6a0cda95905382085f2708ec5f827e9",
+ "sha256": "bf3f56900a7025cb3e9e455f8c6aa6380702697188fbe1c9287a9726b92be7cd"
+ },
+ "downloads": -1,
+ "filename": "pendulum-2.0.0a0-cp34-cp34m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "b6a0cda95905382085f2708ec5f827e9",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp34",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 133629,
+ "upload_time": "2018-04-16T22:32:01",
+ "url": "https://files.pythonhosted.org/packages/0e/3a/9242df09fbb059671216205b93a8aa75564bf56aa6ee2528052a1796d6ec/pendulum-2.0.0a0-cp34-cp34m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "93b9cf76c26dfc3139fefaab6742971a",
+ "sha256": "c4dc5920be16283c1d5c948366cf0f3e3d2c66ac3228255c83738ed44ee08840"
+ },
+ "downloads": -1,
+ "filename": "pendulum-2.0.0a0-cp35-cp35m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "93b9cf76c26dfc3139fefaab6742971a",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 133343,
+ "upload_time": "2018-04-16T22:31:56",
+ "url": "https://files.pythonhosted.org/packages/51/f0/3e540bc4282bac0e241780a6b2aa3e3d55ce19e4bf5c7cd53ba30e5247f4/pendulum-2.0.0a0-cp35-cp35m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "2f89ed35ddc752b78f8b439372d4a099",
+ "sha256": "a803482994d5b7b96781a4eb23566ebefd8372b4aa2e467c079864130f36cf31"
+ },
+ "downloads": -1,
+ "filename": "pendulum-2.0.0a0-cp35-cp35m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "2f89ed35ddc752b78f8b439372d4a099",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 134036,
+ "upload_time": "2018-04-16T22:32:03",
+ "url": "https://files.pythonhosted.org/packages/ce/72/7e445077cbc58060acf4ad18b4ecff5ed3e443779913ab41cc15d4421816/pendulum-2.0.0a0-cp35-cp35m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "7d0ce32fc1b337011c5372f102180a5f",
+ "sha256": "3afa4978b48badeae513b62a311af7e584c04347051af960cd4acad179fe5357"
+ },
+ "downloads": -1,
+ "filename": "pendulum-2.0.0a0-cp36-cp36m-macosx_10_13_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "7d0ce32fc1b337011c5372f102180a5f",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp36",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 405506,
+ "upload_time": "2018-04-16T22:32:00",
+ "url": "https://files.pythonhosted.org/packages/58/9a/6d1af34ad26873264e3269b5a202291ad908318326b6772e9074c6ac37f6/pendulum-2.0.0a0-cp36-cp36m-macosx_10_13_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "e7e5b8552e74c4593c267d7fcdca92f5",
+ "sha256": "216de609ede284b5d6e00542f47360f4e532747c632d56b2851512822063feef"
+ },
+ "downloads": -1,
+ "filename": "pendulum-2.0.0a0-cp36-cp36m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "e7e5b8552e74c4593c267d7fcdca92f5",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp36",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 133479,
+ "upload_time": "2018-04-16T22:31:53",
+ "url": "https://files.pythonhosted.org/packages/9c/7a/65b6ff6e2a74289f90e1f844940838e25367abc22a306f5e1012e02bef7f/pendulum-2.0.0a0-cp36-cp36m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "3820953821fdc78dfdf583f9209a9000",
+ "sha256": "abded7c81aea2aa55846720820aeb36ba64994b4eac5c56556cfccc4473ad1f8"
+ },
+ "downloads": -1,
+ "filename": "pendulum-2.0.0a0-cp36-cp36m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "3820953821fdc78dfdf583f9209a9000",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp36",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 134177,
+ "upload_time": "2018-04-16T22:31:59",
+ "url": "https://files.pythonhosted.org/packages/67/ad/c231079dc8430d3a6a6a38e5406d2f129876647ddb238dcaaca3aa2287e6/pendulum-2.0.0a0-cp36-cp36m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "bb9f11b92775e74a631371402a05c90e",
+ "sha256": "cb7de9b6795d12a840a3b913d70dc94063a659e5268cfd1b955e4fbd2c0709fd"
+ },
+ "downloads": -1,
+ "filename": "pendulum-2.0.0a0.tar.gz",
+ "has_sig": false,
+ "md5_digest": "bb9f11b92775e74a631371402a05c90e",
+ "packagetype": "sdist",
+ "python_version": "source",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 71572,
+ "upload_time": "2018-04-16T22:31:55",
+ "url": "https://files.pythonhosted.org/packages/60/16/1d1a5f7a05fd548df719a9ce22548525e4ae730cbd7ac2ed72d532ee7b8a/pendulum-2.0.0a0.tar.gz"
+ }
+ ],
+ "2.0.1": [
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "92d48ff85f259293b96caae9a71b576d",
+ "sha256": "4ff30c1e78e2e2f9b9caa833e04106a45502fe4504c2da88fd56c3da983b339a"
+ },
+ "downloads": -1,
+ "filename": "pendulum-2.0.1-cp27-cp27m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "92d48ff85f259293b96caae9a71b576d",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 92785,
+ "upload_time": "2018-05-10T22:31:41",
+ "url": "https://files.pythonhosted.org/packages/97/36/2c717ce98be1969072214bbc2180ea5799091daa0f031e95c697983243cc/pendulum-2.0.1-cp27-cp27m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "2e5ba2fd039f52c60a469f605af00ccd",
+ "sha256": "999ad7c9975b5ecc03b4fc2bbd7853650f3a272320bf92b3526601d008826c53"
+ },
+ "downloads": -1,
+ "filename": "pendulum-2.0.1-cp27-cp27m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "2e5ba2fd039f52c60a469f605af00ccd",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 92789,
+ "upload_time": "2018-05-10T22:31:40",
+ "url": "https://files.pythonhosted.org/packages/6d/f5/20ed519a3e94f03f69ccf405aa413bdb2067e9a488a53c039b708a4fe69e/pendulum-2.0.1-cp27-cp27m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "a3fb1a810f14d16c763aea0aa5b4ac05",
+ "sha256": "6dc3c640cee078245271d407ce4fe74217518a57d5bd404addc017083c35cf9c"
+ },
+ "downloads": -1,
+ "filename": "pendulum-2.0.1-cp34-cp34m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "a3fb1a810f14d16c763aea0aa5b4ac05",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp34",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 136057,
+ "upload_time": "2018-05-10T22:31:34",
+ "url": "https://files.pythonhosted.org/packages/fd/17/6970d07b77ab6e7729df937b90619d4b41a5885d55f217e8bd0d5a7443f2/pendulum-2.0.1-cp34-cp34m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "86400f8c825ce216fd0d2058f6f4b2fd",
+ "sha256": "0671c69452adaa685b3c6923ac7fc10b0b86e0c05bdad3c80bfa962e1e730f5b"
+ },
+ "downloads": -1,
+ "filename": "pendulum-2.0.1-cp34-cp34m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "86400f8c825ce216fd0d2058f6f4b2fd",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp34",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 136676,
+ "upload_time": "2018-05-10T22:31:36",
+ "url": "https://files.pythonhosted.org/packages/12/b6/fc2b3ed8d3b8fe2f9e1189af7ad6fb1578c4e70e84bc18752d2e6a025d85/pendulum-2.0.1-cp34-cp34m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "01ae438915792f566a9d5b8b166219fa",
+ "sha256": "a2d2e50890400a258166a7cfdf1a01164aa16bd402fd8b404c7131c3d9cf7c55"
+ },
+ "downloads": -1,
+ "filename": "pendulum-2.0.1-cp35-cp35m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "01ae438915792f566a9d5b8b166219fa",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 136402,
+ "upload_time": "2018-05-10T22:31:38",
+ "url": "https://files.pythonhosted.org/packages/95/fc/6d8922093705fd34d4d2301616c3c9e5a18e7532b2e1ef4ef8b08f0e1986/pendulum-2.0.1-cp35-cp35m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "be2b855c4d16afb3e7e503bd84245e4d",
+ "sha256": "deb2f38ac2fac5759094bcf0e0344154d3b0d5b2fe2b8962a533cdc4e67f609d"
+ },
+ "downloads": -1,
+ "filename": "pendulum-2.0.1-cp35-cp35m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "be2b855c4d16afb3e7e503bd84245e4d",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 137079,
+ "upload_time": "2018-05-10T22:31:33",
+ "url": "https://files.pythonhosted.org/packages/22/d4/64d604c7e8188bfa5275e5682cc26963db17c84aa14df37aa5d2489aee4c/pendulum-2.0.1-cp35-cp35m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "9ae4ac800a27bbf867e878217969299e",
+ "sha256": "69c305e436402caa49e782e5dfc766b5a0b17a74d40acdbd1cefcf589ab90c88"
+ },
+ "downloads": -1,
+ "filename": "pendulum-2.0.1-cp36-cp36m-macosx_10_13_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "9ae4ac800a27bbf867e878217969299e",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp36",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 415509,
+ "upload_time": "2018-05-10T22:31:37",
+ "url": "https://files.pythonhosted.org/packages/2e/d7/6ff80fd281016da9caeca53560ff60b9119a4d0152c6232240e1903652eb/pendulum-2.0.1-cp36-cp36m-macosx_10_13_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "c9cb639e237afb6527bfd00c067e919e",
+ "sha256": "d85e4f62547f681f59aefbe50606f161d9318103b35515edccce48c50fc373ff"
+ },
+ "downloads": -1,
+ "filename": "pendulum-2.0.1-cp36-cp36m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "c9cb639e237afb6527bfd00c067e919e",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp36",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 136531,
+ "upload_time": "2018-05-10T22:31:44",
+ "url": "https://files.pythonhosted.org/packages/69/af/f6e5d94fadd5aab2e696ffeb66f095f2ec356dda3bc1f2b8d1e5424360be/pendulum-2.0.1-cp36-cp36m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "9750e9d6b0f188354878356b91050a31",
+ "sha256": "930507c3af387315aca21cd7b1ba8148e7a0875aaa70f28de2f0f4fff61c70c5"
+ },
+ "downloads": -1,
+ "filename": "pendulum-2.0.1-cp36-cp36m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "9750e9d6b0f188354878356b91050a31",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp36",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 137224,
+ "upload_time": "2018-05-10T22:31:43",
+ "url": "https://files.pythonhosted.org/packages/2e/4a/6ee21cd283e5961e2401f5eaebfc86301966ccbee9885e191e90bcac8519/pendulum-2.0.1-cp36-cp36m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "86412b5ada2d1ac14b6f52db43be13bd",
+ "sha256": "319eb6507e129ef14517805f4e1dcfcd01f2a8eeac55a61ec8f5d115f145f53e"
+ },
+ "downloads": -1,
+ "filename": "pendulum-2.0.1.tar.gz",
+ "has_sig": false,
+ "md5_digest": "86412b5ada2d1ac14b6f52db43be13bd",
+ "packagetype": "sdist",
+ "python_version": "source",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 74388,
+ "upload_time": "2018-05-10T22:31:42",
+ "url": "https://files.pythonhosted.org/packages/6a/60/458ac3edab4bb614033219f265e3662f5c3635a8b4680fa826d912943ceb/pendulum-2.0.1.tar.gz"
+ }
+ ],
+ "2.0.2": [
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "ecfb2f1e99a78daaa005764576d338cb",
+ "sha256": "d8822a592bbc16576c44ec4625bff9187ed9b649d47714e4905a55adc5b25339"
+ },
+ "downloads": -1,
+ "filename": "pendulum-2.0.2-cp27-cp27m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "ecfb2f1e99a78daaa005764576d338cb",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 93895,
+ "upload_time": "2018-05-29T15:44:08",
+ "url": "https://files.pythonhosted.org/packages/63/8f/2fe5a9f09d367c7c3988612539fef5c125c294721ff17d87bf06b04de031/pendulum-2.0.2-cp27-cp27m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "e68530224501ce8cb3c43857a01e8500",
+ "sha256": "8bb523f759daeecfc0649369f198cbeb27a6608347354f4f847d21d579003db6"
+ },
+ "downloads": -1,
+ "filename": "pendulum-2.0.2-cp27-cp27m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "e68530224501ce8cb3c43857a01e8500",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 93898,
+ "upload_time": "2018-05-29T15:44:10",
+ "url": "https://files.pythonhosted.org/packages/aa/fd/0e284be7e9659fa9786d3b56cc72c672d3fb12bd961396a84566e4fe8de0/pendulum-2.0.2-cp27-cp27m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "f7db79c4bfa56592302e383bdde5307a",
+ "sha256": "846478ab5f7480b3d850a09e44fe03830d448633c84f0b1066615ff6c34293aa"
+ },
+ "downloads": -1,
+ "filename": "pendulum-2.0.2-cp34-cp34m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "f7db79c4bfa56592302e383bdde5307a",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp34",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 138256,
+ "upload_time": "2018-05-29T15:44:11",
+ "url": "https://files.pythonhosted.org/packages/03/33/5c7b72707dfbf2dcb69e1578d7447023c76bab7cc72ec6f81703fda50932/pendulum-2.0.2-cp34-cp34m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "71037c76a9a7a83c2df98d737748c5a1",
+ "sha256": "b7ff156b3d7cccbdeeb63465578d9a4e6f57d463f6ff6d4474254208d08f8353"
+ },
+ "downloads": -1,
+ "filename": "pendulum-2.0.2-cp34-cp34m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "71037c76a9a7a83c2df98d737748c5a1",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp34",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 139047,
+ "upload_time": "2018-05-29T15:44:13",
+ "url": "https://files.pythonhosted.org/packages/9d/87/ec9ce14a6e6a499f34403cdcaa027993a0c24049e2f73333a1fab0ed6f5f/pendulum-2.0.2-cp34-cp34m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "3605720bcdb9beee38e59c7d8c848025",
+ "sha256": "0643d45824e6789b88187728337dfa6075a0233f6976c2abefba00d064156309"
+ },
+ "downloads": -1,
+ "filename": "pendulum-2.0.2-cp35-cp35m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "3605720bcdb9beee38e59c7d8c848025",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 138607,
+ "upload_time": "2018-05-29T15:44:14",
+ "url": "https://files.pythonhosted.org/packages/fb/86/43aa0146f10ba0f11c9ac41a661749ea01802b1902706006cf73b74e2dd8/pendulum-2.0.2-cp35-cp35m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "e44f7c8e7b94abf51436108068bb3bce",
+ "sha256": "dd45c7b349faab69714df9835cdf8bf8bce50bf6fc471419d3b23ba33e1915a5"
+ },
+ "downloads": -1,
+ "filename": "pendulum-2.0.2-cp35-cp35m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "e44f7c8e7b94abf51436108068bb3bce",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 139444,
+ "upload_time": "2018-05-29T15:44:16",
+ "url": "https://files.pythonhosted.org/packages/31/dd/7c8f7fd020b2799402ef4937a2b633f21e36b63ef0c30208419d4cd523fe/pendulum-2.0.2-cp35-cp35m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "6287c466529bbb2f6d356914de298a67",
+ "sha256": "3cc271195d8054bec06f54ff7d56ea6c2e2b5ad5dd6b532d787b34d2cabe6a65"
+ },
+ "downloads": -1,
+ "filename": "pendulum-2.0.2-cp36-cp36m-macosx_10_13_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "6287c466529bbb2f6d356914de298a67",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp36",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 418851,
+ "upload_time": "2018-05-29T15:44:17",
+ "url": "https://files.pythonhosted.org/packages/e7/59/e90aae0663f99d5347126f6b95e39a3c25bbc127b2c545110baa11ff203c/pendulum-2.0.2-cp36-cp36m-macosx_10_13_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "2a854d7113fb582d8c92746ac1da03ec",
+ "sha256": "a449142063100f1b3c1119453c7569667c9ba79897305a1c50ca83a8c790f1e4"
+ },
+ "downloads": -1,
+ "filename": "pendulum-2.0.2-cp36-cp36m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "2a854d7113fb582d8c92746ac1da03ec",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp36",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 138709,
+ "upload_time": "2018-05-29T15:44:19",
+ "url": "https://files.pythonhosted.org/packages/40/f5/0ba6f561ec72e5875d372bc215f497c7d814e0f6faf66c928ebb89b0515e/pendulum-2.0.2-cp36-cp36m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "d2b9f35f6ade3f9791b51bc3afa6e99c",
+ "sha256": "fac088b637b5db5a047a0e89194d8c3c9e9e9ce1665089240003bb7c05b92536"
+ },
+ "downloads": -1,
+ "filename": "pendulum-2.0.2-cp36-cp36m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "d2b9f35f6ade3f9791b51bc3afa6e99c",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp36",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 139557,
+ "upload_time": "2018-05-29T15:44:20",
+ "url": "https://files.pythonhosted.org/packages/b1/cb/56de72fc5ea6dc9089ccb673d37c18d98c151004675e273da46ab89a4378/pendulum-2.0.2-cp36-cp36m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "f8887ecab60f7df8deacd321d706292e",
+ "sha256": "544e44d8a92954e5ef4db4fa8b662d3282f2ac7b7c2cbf4227dc193ba78b9e1e"
+ },
+ "downloads": -1,
+ "filename": "pendulum-2.0.2.tar.gz",
+ "has_sig": false,
+ "md5_digest": "f8887ecab60f7df8deacd321d706292e",
+ "packagetype": "sdist",
+ "python_version": "source",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 75502,
+ "upload_time": "2018-05-29T15:44:22",
+ "url": "https://files.pythonhosted.org/packages/4a/97/c288b8c98e49b9e1ec67b28ada3f39b7bd786be11ca119244e2aca3a5cf4/pendulum-2.0.2.tar.gz"
+ }
+ ],
+ "2.0.3": [
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "279b638363f3e37b7cf0adbf72e851f3",
+ "sha256": "f7fa6220251a636112721e8158b9dd59018d818ec121047900934d80864eca62"
+ },
+ "downloads": -1,
+ "filename": "pendulum-2.0.3-cp27-cp27m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "279b638363f3e37b7cf0adbf72e851f3",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 93932,
+ "upload_time": "2018-07-30T21:18:21",
+ "url": "https://files.pythonhosted.org/packages/25/9d/a4e5f81aecfbbfe97ccd12a0285000dea9baadd20a676f0ea9cbbdd2654d/pendulum-2.0.3-cp27-cp27m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "273ea498e638def03dfd32b41333a266",
+ "sha256": "c358ee65ddb99c2b1bf301458e43ed09ff6d40465bcc9928265246912fad4d0f"
+ },
+ "downloads": -1,
+ "filename": "pendulum-2.0.3-cp27-cp27m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "273ea498e638def03dfd32b41333a266",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 93937,
+ "upload_time": "2018-07-30T21:18:23",
+ "url": "https://files.pythonhosted.org/packages/17/ad/ae5c3442161cd3cbf242aa4e550cfb3880502dce7d161c0b99b9372591b5/pendulum-2.0.3-cp27-cp27m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "bb0ad49504aaab982b8ff26f51e9f8ca",
+ "sha256": "c0401482dfa9fbd7005f2dfbf54ec61fd2c8130df37651ac2a3722d1f049ae4e"
+ },
+ "downloads": -1,
+ "filename": "pendulum-2.0.3-cp34-cp34m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "bb0ad49504aaab982b8ff26f51e9f8ca",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp34",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 138312,
+ "upload_time": "2018-07-30T21:18:24",
+ "url": "https://files.pythonhosted.org/packages/9a/06/20dc497a97cc6e07ad32eacda98e63188514a4f6d77e7bf8febfaeccf4f2/pendulum-2.0.3-cp34-cp34m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "fb35aff4e533090f6169acaf06756374",
+ "sha256": "10ccdc8c6d004ba97883dd0f57503963ddf6cb83e849a16c4675ba18da657564"
+ },
+ "downloads": -1,
+ "filename": "pendulum-2.0.3-cp34-cp34m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "fb35aff4e533090f6169acaf06756374",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp34",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 139084,
+ "upload_time": "2018-07-30T21:18:25",
+ "url": "https://files.pythonhosted.org/packages/3d/d2/44a0592a46b9ca119d5c4a4ee92a000c84d9d8e0e22f24ea7d62f7b1f4b6/pendulum-2.0.3-cp34-cp34m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "bd4151dd2247edd4b7889c01dba55a39",
+ "sha256": "51803352e40778f914ff7af3494788b404260b415d9a9d607a8cf73e5e120994"
+ },
+ "downloads": -1,
+ "filename": "pendulum-2.0.3-cp35-cp35m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "bd4151dd2247edd4b7889c01dba55a39",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 138657,
+ "upload_time": "2018-07-30T21:18:27",
+ "url": "https://files.pythonhosted.org/packages/84/b7/537a071ac5e0212f2c72d65cda1b8c3240a6edf18e6a1a6268e744e4e42b/pendulum-2.0.3-cp35-cp35m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "0f49bcbbbfc85ce1cede4d43d802764c",
+ "sha256": "37bb54bcbb9d7fccd725f3fda69702e51ab3de9971b4c1c986505fbb3bc58bed"
+ },
+ "downloads": -1,
+ "filename": "pendulum-2.0.3-cp35-cp35m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "0f49bcbbbfc85ce1cede4d43d802764c",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 139471,
+ "upload_time": "2018-07-30T21:18:28",
+ "url": "https://files.pythonhosted.org/packages/a9/bb/19c145dc096828014f2c1e51edb33bd4d5f92270187f6e19ca30fd349df1/pendulum-2.0.3-cp35-cp35m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "0476855d81dc2357606295a55e6b6904",
+ "sha256": "dc05e6186c9c3b9969326aded9cba7a796744918581b25457f5148a5e3475d55"
+ },
+ "downloads": -1,
+ "filename": "pendulum-2.0.3-cp36-cp36m-macosx_10_13_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "0476855d81dc2357606295a55e6b6904",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp36",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 419341,
+ "upload_time": "2018-07-30T21:18:29",
+ "url": "https://files.pythonhosted.org/packages/13/21/6e922a6c8d8ade424c7cbf1fb3a1f47f7af1cd537ffb20b3ed9c5a75a39b/pendulum-2.0.3-cp36-cp36m-macosx_10_13_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "d38df7d7b2e18add95dd822350725741",
+ "sha256": "73f850265adcf0986fcc0af83ae9c8c5a7ca3c4a2525184110478a8bfd1a77b3"
+ },
+ "downloads": -1,
+ "filename": "pendulum-2.0.3-cp36-cp36m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "d38df7d7b2e18add95dd822350725741",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp36",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 138752,
+ "upload_time": "2018-07-30T21:18:31",
+ "url": "https://files.pythonhosted.org/packages/d8/dd/283d9042284351bc05ad8a4cbcf955adadcf9f5478b4b3ade2ab5782ac07/pendulum-2.0.3-cp36-cp36m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "e5d548725648c494fc9c59328684aee9",
+ "sha256": "ee9466eea403e8e308c284d3055e285b97905a5ffb1566df0ef200b4f39c0f15"
+ },
+ "downloads": -1,
+ "filename": "pendulum-2.0.3-cp36-cp36m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "e5d548725648c494fc9c59328684aee9",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp36",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 139618,
+ "upload_time": "2018-07-30T21:18:32",
+ "url": "https://files.pythonhosted.org/packages/b0/2b/1699eb626ce9bb79dcf710349b0eb45318cd38ad1c1dda3c95802fa0570f/pendulum-2.0.3-cp36-cp36m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "fa8aac5207ff8c60d256f0f92ef506ba",
+ "sha256": "0ec5371949e147753661e1e98721273170638034dfceb578f29d69d93d3d474b"
+ },
+ "downloads": -1,
+ "filename": "pendulum-2.0.3-cp37-cp37m-macosx_10_13_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "fa8aac5207ff8c60d256f0f92ef506ba",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp37",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 419340,
+ "upload_time": "2018-07-30T21:18:34",
+ "url": "https://files.pythonhosted.org/packages/4f/82/dc9c47dfd52dfb7002c2c1553f32e1d85a65b0b01986227dfe2f9695d1e0/pendulum-2.0.3-cp37-cp37m-macosx_10_13_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "320a8a20343d04d7bdd6eac4cb32b3c9",
+ "sha256": "5de295ca85761d9adf4020e6f3bed6eb933846ccf23b74e04b071f6d677f11a4"
+ },
+ "downloads": -1,
+ "filename": "pendulum-2.0.3-cp37-cp37m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "320a8a20343d04d7bdd6eac4cb32b3c9",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp37",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 138823,
+ "upload_time": "2018-07-30T21:18:35",
+ "url": "https://files.pythonhosted.org/packages/c1/e6/d225b5aba2d395504183600b8669f279be50732c97a10d0027caf046c462/pendulum-2.0.3-cp37-cp37m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "9e376e70006b99d2b8b0435c498d9174",
+ "sha256": "8fe289356322f6b0f4510082b4c412a1496a64054a37ae86b24411868a1901c6"
+ },
+ "downloads": -1,
+ "filename": "pendulum-2.0.3-cp37-cp37m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "9e376e70006b99d2b8b0435c498d9174",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp37",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 139677,
+ "upload_time": "2018-07-30T21:18:36",
+ "url": "https://files.pythonhosted.org/packages/ac/31/24dfb2212386dc92c71440ed409a7d1a7139e8e042a5df349eaf6b59944d/pendulum-2.0.3-cp37-cp37m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "cc82dda147a51156a5a81817d58500f5",
+ "sha256": "d07962450e808556b3e6209a5830e2bbf8c7747129580c3b5b09e641f72617ab"
+ },
+ "downloads": -1,
+ "filename": "pendulum-2.0.3.tar.gz",
+ "has_sig": false,
+ "md5_digest": "cc82dda147a51156a5a81817d58500f5",
+ "packagetype": "sdist",
+ "python_version": "source",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 75580,
+ "upload_time": "2018-07-30T21:18:37",
+ "url": "https://files.pythonhosted.org/packages/c9/ec/93ed35ccd2b654b22992c78ed5e42e9061aa376b554f89e1d1db54b6c12a/pendulum-2.0.3.tar.gz"
+ }
+ ]
+ },
+ "urls": [
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "279b638363f3e37b7cf0adbf72e851f3",
+ "sha256": "f7fa6220251a636112721e8158b9dd59018d818ec121047900934d80864eca62"
+ },
+ "downloads": -1,
+ "filename": "pendulum-2.0.3-cp27-cp27m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "279b638363f3e37b7cf0adbf72e851f3",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 93932,
+ "upload_time": "2018-07-30T21:18:21",
+ "url": "https://files.pythonhosted.org/packages/25/9d/a4e5f81aecfbbfe97ccd12a0285000dea9baadd20a676f0ea9cbbdd2654d/pendulum-2.0.3-cp27-cp27m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "273ea498e638def03dfd32b41333a266",
+ "sha256": "c358ee65ddb99c2b1bf301458e43ed09ff6d40465bcc9928265246912fad4d0f"
+ },
+ "downloads": -1,
+ "filename": "pendulum-2.0.3-cp27-cp27m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "273ea498e638def03dfd32b41333a266",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp27",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 93937,
+ "upload_time": "2018-07-30T21:18:23",
+ "url": "https://files.pythonhosted.org/packages/17/ad/ae5c3442161cd3cbf242aa4e550cfb3880502dce7d161c0b99b9372591b5/pendulum-2.0.3-cp27-cp27m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "bb0ad49504aaab982b8ff26f51e9f8ca",
+ "sha256": "c0401482dfa9fbd7005f2dfbf54ec61fd2c8130df37651ac2a3722d1f049ae4e"
+ },
+ "downloads": -1,
+ "filename": "pendulum-2.0.3-cp34-cp34m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "bb0ad49504aaab982b8ff26f51e9f8ca",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp34",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 138312,
+ "upload_time": "2018-07-30T21:18:24",
+ "url": "https://files.pythonhosted.org/packages/9a/06/20dc497a97cc6e07ad32eacda98e63188514a4f6d77e7bf8febfaeccf4f2/pendulum-2.0.3-cp34-cp34m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "fb35aff4e533090f6169acaf06756374",
+ "sha256": "10ccdc8c6d004ba97883dd0f57503963ddf6cb83e849a16c4675ba18da657564"
+ },
+ "downloads": -1,
+ "filename": "pendulum-2.0.3-cp34-cp34m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "fb35aff4e533090f6169acaf06756374",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp34",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 139084,
+ "upload_time": "2018-07-30T21:18:25",
+ "url": "https://files.pythonhosted.org/packages/3d/d2/44a0592a46b9ca119d5c4a4ee92a000c84d9d8e0e22f24ea7d62f7b1f4b6/pendulum-2.0.3-cp34-cp34m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "bd4151dd2247edd4b7889c01dba55a39",
+ "sha256": "51803352e40778f914ff7af3494788b404260b415d9a9d607a8cf73e5e120994"
+ },
+ "downloads": -1,
+ "filename": "pendulum-2.0.3-cp35-cp35m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "bd4151dd2247edd4b7889c01dba55a39",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 138657,
+ "upload_time": "2018-07-30T21:18:27",
+ "url": "https://files.pythonhosted.org/packages/84/b7/537a071ac5e0212f2c72d65cda1b8c3240a6edf18e6a1a6268e744e4e42b/pendulum-2.0.3-cp35-cp35m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "0f49bcbbbfc85ce1cede4d43d802764c",
+ "sha256": "37bb54bcbb9d7fccd725f3fda69702e51ab3de9971b4c1c986505fbb3bc58bed"
+ },
+ "downloads": -1,
+ "filename": "pendulum-2.0.3-cp35-cp35m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "0f49bcbbbfc85ce1cede4d43d802764c",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp35",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 139471,
+ "upload_time": "2018-07-30T21:18:28",
+ "url": "https://files.pythonhosted.org/packages/a9/bb/19c145dc096828014f2c1e51edb33bd4d5f92270187f6e19ca30fd349df1/pendulum-2.0.3-cp35-cp35m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "0476855d81dc2357606295a55e6b6904",
+ "sha256": "dc05e6186c9c3b9969326aded9cba7a796744918581b25457f5148a5e3475d55"
+ },
+ "downloads": -1,
+ "filename": "pendulum-2.0.3-cp36-cp36m-macosx_10_13_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "0476855d81dc2357606295a55e6b6904",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp36",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 419341,
+ "upload_time": "2018-07-30T21:18:29",
+ "url": "https://files.pythonhosted.org/packages/13/21/6e922a6c8d8ade424c7cbf1fb3a1f47f7af1cd537ffb20b3ed9c5a75a39b/pendulum-2.0.3-cp36-cp36m-macosx_10_13_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "d38df7d7b2e18add95dd822350725741",
+ "sha256": "73f850265adcf0986fcc0af83ae9c8c5a7ca3c4a2525184110478a8bfd1a77b3"
+ },
+ "downloads": -1,
+ "filename": "pendulum-2.0.3-cp36-cp36m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "d38df7d7b2e18add95dd822350725741",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp36",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 138752,
+ "upload_time": "2018-07-30T21:18:31",
+ "url": "https://files.pythonhosted.org/packages/d8/dd/283d9042284351bc05ad8a4cbcf955adadcf9f5478b4b3ade2ab5782ac07/pendulum-2.0.3-cp36-cp36m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "e5d548725648c494fc9c59328684aee9",
+ "sha256": "ee9466eea403e8e308c284d3055e285b97905a5ffb1566df0ef200b4f39c0f15"
+ },
+ "downloads": -1,
+ "filename": "pendulum-2.0.3-cp36-cp36m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "e5d548725648c494fc9c59328684aee9",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp36",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 139618,
+ "upload_time": "2018-07-30T21:18:32",
+ "url": "https://files.pythonhosted.org/packages/b0/2b/1699eb626ce9bb79dcf710349b0eb45318cd38ad1c1dda3c95802fa0570f/pendulum-2.0.3-cp36-cp36m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "fa8aac5207ff8c60d256f0f92ef506ba",
+ "sha256": "0ec5371949e147753661e1e98721273170638034dfceb578f29d69d93d3d474b"
+ },
+ "downloads": -1,
+ "filename": "pendulum-2.0.3-cp37-cp37m-macosx_10_13_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "fa8aac5207ff8c60d256f0f92ef506ba",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp37",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 419340,
+ "upload_time": "2018-07-30T21:18:34",
+ "url": "https://files.pythonhosted.org/packages/4f/82/dc9c47dfd52dfb7002c2c1553f32e1d85a65b0b01986227dfe2f9695d1e0/pendulum-2.0.3-cp37-cp37m-macosx_10_13_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "320a8a20343d04d7bdd6eac4cb32b3c9",
+ "sha256": "5de295ca85761d9adf4020e6f3bed6eb933846ccf23b74e04b071f6d677f11a4"
+ },
+ "downloads": -1,
+ "filename": "pendulum-2.0.3-cp37-cp37m-manylinux1_i686.whl",
+ "has_sig": false,
+ "md5_digest": "320a8a20343d04d7bdd6eac4cb32b3c9",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp37",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 138823,
+ "upload_time": "2018-07-30T21:18:35",
+ "url": "https://files.pythonhosted.org/packages/c1/e6/d225b5aba2d395504183600b8669f279be50732c97a10d0027caf046c462/pendulum-2.0.3-cp37-cp37m-manylinux1_i686.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "9e376e70006b99d2b8b0435c498d9174",
+ "sha256": "8fe289356322f6b0f4510082b4c412a1496a64054a37ae86b24411868a1901c6"
+ },
+ "downloads": -1,
+ "filename": "pendulum-2.0.3-cp37-cp37m-manylinux1_x86_64.whl",
+ "has_sig": false,
+ "md5_digest": "9e376e70006b99d2b8b0435c498d9174",
+ "packagetype": "bdist_wheel",
+ "python_version": "cp37",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 139677,
+ "upload_time": "2018-07-30T21:18:36",
+ "url": "https://files.pythonhosted.org/packages/ac/31/24dfb2212386dc92c71440ed409a7d1a7139e8e042a5df349eaf6b59944d/pendulum-2.0.3-cp37-cp37m-manylinux1_x86_64.whl"
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "md5": "cc82dda147a51156a5a81817d58500f5",
+ "sha256": "d07962450e808556b3e6209a5830e2bbf8c7747129580c3b5b09e641f72617ab"
+ },
+ "downloads": -1,
+ "filename": "pendulum-2.0.3.tar.gz",
+ "has_sig": false,
+ "md5_digest": "cc82dda147a51156a5a81817d58500f5",
+ "packagetype": "sdist",
+ "python_version": "source",
+ "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
+ "size": 75580,
+ "upload_time": "2018-07-30T21:18:37",
+ "url": "https://files.pythonhosted.org/packages/c9/ec/93ed35ccd2b654b22992c78ed5e42e9061aa376b554f89e1d1db54b6c12a/pendulum-2.0.3.tar.gz"
+ }
+ ]
+}
diff --git a/uv/spec/fixtures/pypi/pypi_response_prerelease.json b/uv/spec/fixtures/pypi/pypi_response_prerelease.json
new file mode 100644
index 00000000000..a81824f0f19
--- /dev/null
+++ b/uv/spec/fixtures/pypi/pypi_response_prerelease.json
@@ -0,0 +1,677 @@
+{
+ "info": {
+ "maintainer": "",
+ "docs_url": null,
+ "requires_python": "",
+ "maintainer_email": "",
+ "cheesecake_code_kwalitee_id": null,
+ "keywords": "",
+ "package_url": "http://pypi.org/pypi/luigi",
+ "author": "The Luigi Authors",
+ "author_email": "",
+ "download_url": "",
+ "platform": "",
+ "version": "2.6.0.beta1",
+ "cheesecake_documentation_id": null,
+ "_pypi_hidden": false,
+ "description": ".. note::\n\n For the latest source, discussion, etc, please visit the\n `GitHub repository `_\n\n\n.. figure:: https://raw.githubusercontent.com/spotify/luigi/master/doc/luigi.png\n :alt: Luigi Logo\n :align: center\n\n.. image:: https://img.shields.io/travis/spotify/luigi/master.svg?style=flat\n :target: https://travis-ci.org/spotify/luigi\n\n.. image:: https://img.shields.io/codecov/c/github/spotify/luigi/master.svg?style=flat\n :target: https://codecov.io/gh/spotify/luigi?branch=master\n\n.. image:: https://landscape.io/github/spotify/luigi/master/landscape.svg?style=flat\n :target: https://landscape.io/github/spotify/luigi/master\n\n.. image:: https://img.shields.io/pypi/v/luigi.svg?style=flat\n :target: https://pypi.org/pypi/luigi\n\n.. image:: https://img.shields.io/pypi/l/luigi.svg?style=flat\n :target: https://pypi.org/pypi/luigi\n\nLuigi is a Python (2.7, 3.3, 3.4, 3.5) package that helps you build complex pipelines of batch\njobs. It handles dependency resolution, workflow management, visualization,\nhandling failures, command line integration, and much more.\n\nGetting Started\n---------------\n\nRun ``pip install luigi`` to install the latest stable version from `PyPI\n`_. Documentation for the latest release is\nhosted `here `__.\n\nFor the bleeding edge code, ``pip install\ngit+https://github.com/spotify/luigi.git``. Bleeding edge documentation can be\nfound `here `__.\n\nBackground\n----------\n\nThe purpose of Luigi is to address all the plumbing typically associated\nwith long-running batch processes. You want to chain many tasks,\nautomate them, and failures *will* happen. These tasks can be anything,\nbut are typically long running things like\n`Hadoop `_ jobs, dumping data to/from\ndatabases, running machine learning algorithms, or anything else.\n\nThere are other software packages that focus on lower level aspects of\ndata processing, like `Hive `__,\n`Pig `_, or\n`Cascading `_. Luigi is not a framework to\nreplace these. Instead it helps you stitch many tasks together, where\neach task can be a `Hive query `__,\na `Hadoop job in Java `_,\na `Spark job in Scala or Python `_\na Python snippet,\n`dumping a table `_\nfrom a database, or anything else. It's easy to build up\nlong-running pipelines that comprise thousands of tasks and take days or\nweeks to complete. Luigi takes care of a lot of the workflow management\nso that you can focus on the tasks themselves and their dependencies.\n\nYou can build pretty much any task you want, but Luigi also comes with a\n*toolbox* of several common task templates that you use. It includes\nsupport for running\n`Python mapreduce jobs `_\nin Hadoop, as well as\n`Hive `__,\nand `Pig `__,\njobs. It also comes with\n`file system abstractions for HDFS `_,\nand local files that ensures all file system operations are atomic. This\nis important because it means your data pipeline will not crash in a\nstate containing partial data.\n\nVisualiser page\n---------------\n\nThe Luigi server comes with a web interface too, so you can search and filter\namong all your tasks.\n\n.. figure:: https://raw.githubusercontent.com/spotify/luigi/master/doc/visualiser_front_page.png\n :alt: Visualiser page\n\nDependency graph example\n------------------------\n\nJust to give you an idea of what Luigi does, this is a screen shot from\nsomething we are running in production. Using Luigi's visualiser, we get\na nice visual overview of the dependency graph of the workflow. Each\nnode represents a task which has to be run. Green tasks are already\ncompleted whereas yellow tasks are yet to be run. Most of these tasks\nare Hadoop jobs, but there are also some things that run locally and\nbuild up data files.\n\n.. figure:: https://raw.githubusercontent.com/spotify/luigi/master/doc/user_recs.png\n :alt: Dependency graph\n\nPhilosophy\n----------\n\nConceptually, Luigi is similar to `GNU\nMake `_ where you have certain tasks\nand these tasks in turn may have dependencies on other tasks. There are\nalso some similarities to `Oozie `_\nand `Azkaban `_. One major\ndifference is that Luigi is not just built specifically for Hadoop, and\nit's easy to extend it with other kinds of tasks.\n\nEverything in Luigi is in Python. Instead of XML configuration or\nsimilar external data files, the dependency graph is specified *within\nPython*. This makes it easy to build up complex dependency graphs of\ntasks, where the dependencies can involve date algebra or recursive\nreferences to other versions of the same task. However, the workflow can\ntrigger things not in Python, such as running\n`Pig scripts `_\nor `scp'ing files `_.\n\nWho uses Luigi?\n---------------\n\nWe use Luigi internally at `Spotify `_ to run\nthousands of tasks every day, organized in complex dependency graphs.\nMost of these tasks are Hadoop jobs. Luigi provides an infrastructure\nthat powers all kinds of stuff including recommendations, toplists, A/B\ntest analysis, external reports, internal dashboards, etc.\n\nSince Luigi is open source and without any registration walls, the exact number\nof Luigi users is unknown. But based on the number of unique contributors, we\nexpect hundreds of enterprises to use it. Some users have written blog posts\nor held presentations about Luigi:\n\n* `Spotify (NYC Data Science) `_\n* `Foursquare `_\n* `Mortar Data `_\n* `Stripe `_\n* `Asana `_\n* `Buffer `_\n* `SeatGeek `_\n* `Treasure Data `_\n* `Growth Intelligence `_\n* `AdRoll `_\n* `Schibsted `_\n* `17zuoye `_\n* `enbrite.ly `_\n* `Dow Jones / The Wall Street Journal `_\n* `Hotels.com `_\n* `Custobar (Metrics Monday Helsinki) `_\n* `Blendle `_\n* `TrustYou (PyData Berlin 2015) `_\n* `Groupon / OrderUp `_\n\nWe're more than happy to have your company added here. Just send a PR on GitHub.\n\nExternal links\n--------------\n\n* `Mailing List `_ for discussions and asking questions. (Google Groups)\n* `Releases `_ (PyPI)\n* `Source code `_ (Github)\n* `Hubot Integration `_ plugin for Slack, Hipchat, etc (Github)\n\nAuthors\n-------\n\nLuigi was built at `Spotify `_, mainly by\n`Erik Bernhardsson `_ and\n`Elias Freider `_.\n`Many other people `_\nhave contributed since open sourcing in late 2012.\n`Arash Rouhani `_ is currently the chief\nmaintainer of Luigi.\n",
+ "release_url": "http://pypi.org/pypi/luigi/2.6.0.beta1",
+ "downloads": {
+ "last_month": 0,
+ "last_week": 0,
+ "last_day": 0
+ },
+ "_pypi_ordering": 41,
+ "classifiers": [
+ "Development Status :: 5 - Production/Stable",
+ "Environment :: Console",
+ "Environment :: Web Environment",
+ "Intended Audience :: Developers",
+ "Intended Audience :: System Administrators",
+ "License :: OSI Approved :: Apache Software License",
+ "Programming Language :: Python :: 2.7",
+ "Programming Language :: Python :: 3.3",
+ "Programming Language :: Python :: 3.4",
+ "Programming Language :: Python :: 3.5",
+ "Topic :: System :: Monitoring"
+ ],
+ "bugtrack_url": null,
+ "name": "luigi",
+ "license": "Apache License 2.0",
+ "summary": "Workflow mgmgt + task scheduling + dependency resolution",
+ "home_page": "https://github.com/spotify/luigi",
+ "cheesecake_installability_id": null
+ },
+ "releases": {
+ "1.1.1": [
+ {
+ "has_sig": false,
+ "upload_time": "2015-03-16T13:02:09",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/59/d2/5f32dc62bfa1b430cb902bcd26c652f9fe4c9462a3b06bc1ca6e80127d85/luigi-1.1.1.tar.gz",
+ "md5_digest": "5659011287f08ff6f1a36f9b9ab04269",
+ "downloads": 2776,
+ "filename": "luigi-1.1.1.tar.gz",
+ "packagetype": "sdist",
+ "path": "59/d2/5f32dc62bfa1b430cb902bcd26c652f9fe4c9462a3b06bc1ca6e80127d85/luigi-1.1.1.tar.gz",
+ "size": 357235
+ }
+ ],
+ "1.1.0": [
+ {
+ "has_sig": false,
+ "upload_time": "2015-03-07T17:29:44",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/85/b8/7a89ec0981570ae1fd30f102c8410381770db7898bbfdea3e1aa3ddd3b43/luigi-1.1.0.tar.gz",
+ "md5_digest": "742e9d7acbdceb007c5280b9e9f0f00d",
+ "downloads": 2713,
+ "filename": "luigi-1.1.0.tar.gz",
+ "packagetype": "sdist",
+ "path": "85/b8/7a89ec0981570ae1fd30f102c8410381770db7898bbfdea3e1aa3ddd3b43/luigi-1.1.0.tar.gz",
+ "size": 349728
+ }
+ ],
+ "1.0.6": [
+ {
+ "has_sig": false,
+ "upload_time": "2013-08-07T23:47:21",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/e9/3d/68c6ca27f4bda9aabfef3c58c2866cf5db6e05524162d36b3adb4e8fa8e5/luigi-1.0.6.tar.gz",
+ "md5_digest": "173f1868d0f8c318b2f9e91036d9bff2",
+ "downloads": 2153,
+ "filename": "luigi-1.0.6.tar.gz",
+ "packagetype": "sdist",
+ "path": "e9/3d/68c6ca27f4bda9aabfef3c58c2866cf5db6e05524162d36b3adb4e8fa8e5/luigi-1.0.6.tar.gz",
+ "size": 225527
+ }
+ ],
+ "1.1.2": [
+ {
+ "has_sig": false,
+ "upload_time": "2015-03-18T00:50:52",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/3d/26/191da8144fd2a881f72c6d87df68ee654e684989dcaa3559dcbc9c0a6355/luigi-1.1.2.tar.gz",
+ "md5_digest": "a617f82f1354c49cb227b7877d3defa2",
+ "downloads": 44221,
+ "filename": "luigi-1.1.2.tar.gz",
+ "packagetype": "sdist",
+ "path": "3d/26/191da8144fd2a881f72c6d87df68ee654e684989dcaa3559dcbc9c0a6355/luigi-1.1.2.tar.gz",
+ "size": 357305
+ }
+ ],
+ "1.0.5": [
+ {
+ "has_sig": false,
+ "upload_time": "2013-08-07T23:44:22",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/8c/16/4ac01f87ecb5f1cd1b083003cdaa485f1d4445817dd67fa4145d35243936/luigi-1.0.5.tar.gz",
+ "md5_digest": "15ab75ef16b5c9164f8cf7dfbbd78ef8",
+ "downloads": 2159,
+ "filename": "luigi-1.0.5.tar.gz",
+ "packagetype": "sdist",
+ "path": "8c/16/4ac01f87ecb5f1cd1b083003cdaa485f1d4445817dd67fa4145d35243936/luigi-1.0.5.tar.gz",
+ "size": 225340
+ }
+ ],
+ "1b": [
+ {
+ "has_sig": false,
+ "upload_time": "2013-04-23T00:07:42",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/ab/b3/47b0977818f72172e8385fa10775943e5e8546ff5b6a6867e9b048af1fbe/luigi-1b.tar.gz",
+ "md5_digest": "884b7bd6b966ef4b00ec8a99d1cb5f98",
+ "downloads": 2280,
+ "filename": "luigi-1b.tar.gz",
+ "packagetype": "sdist",
+ "path": "ab/b3/47b0977818f72172e8385fa10775943e5e8546ff5b6a6867e9b048af1fbe/luigi-1b.tar.gz",
+ "size": 93270
+ }
+ ],
+ "2.0.1": [
+ {
+ "has_sig": false,
+ "upload_time": "2015-12-05T18:01:06",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/d4/2a/d6bff91d5ebb22449acb84b8212fd05d19e70713c16b092bfea4c2d2ce21/luigi-2.0.1.tar.gz",
+ "md5_digest": "625b7609fd6566fb14c25c8f2592d95f",
+ "downloads": 40965,
+ "filename": "luigi-2.0.1.tar.gz",
+ "packagetype": "sdist",
+ "path": "d4/2a/d6bff91d5ebb22449acb84b8212fd05d19e70713c16b092bfea4c2d2ce21/luigi-2.0.1.tar.gz",
+ "size": 1089311
+ }
+ ],
+ "2.0.0": [
+ {
+ "has_sig": false,
+ "upload_time": "2015-10-23T12:32:11",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/f6/b6/92a5de1c1d04e579183b97cc2aa1e9fabface3d096ebba5a28842b9db1bf/luigi-2.0.0.tar.gz",
+ "md5_digest": "06258afcfcdd2f829167450fd5fed604",
+ "downloads": 28712,
+ "filename": "luigi-2.0.0.tar.gz",
+ "packagetype": "sdist",
+ "path": "f6/b6/92a5de1c1d04e579183b97cc2aa1e9fabface3d096ebba5a28842b9db1bf/luigi-2.0.0.tar.gz",
+ "size": 1089886
+ }
+ ],
+ "1.0.8": [],
+ "1.0.9": [
+ {
+ "has_sig": false,
+ "upload_time": "2013-08-09T16:05:56",
+ "comment_text": "built for Darwin-11.4.2",
+ "python_version": "any",
+ "url": "https://pypi.org/packages/b4/76/0a96b93f10d6b1cbfec203c8b07fcfe67f209ac1c43f22572ff9e42fc8ca/luigi-1.0.9.macosx-10.7-intel.tar.gz",
+ "md5_digest": "c64aeabe850d1f6235ba353cc89f9174",
+ "downloads": 2115,
+ "filename": "luigi-1.0.9.macosx-10.7-intel.tar.gz",
+ "packagetype": "bdist_dumb",
+ "path": "b4/76/0a96b93f10d6b1cbfec203c8b07fcfe67f209ac1c43f22572ff9e42fc8ca/luigi-1.0.9.macosx-10.7-intel.tar.gz",
+ "size": 284105
+ },
+ {
+ "has_sig": false,
+ "upload_time": "2013-08-09T16:05:58",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/01/75/6fa1e73a8fda67c02da29189541be78577c8535ea7b721e4c5c3b62a7fcc/luigi-1.0.9.tar.gz",
+ "md5_digest": "024834d21a13276e84346fc000ff8cb4",
+ "downloads": 2156,
+ "filename": "luigi-1.0.9.tar.gz",
+ "packagetype": "sdist",
+ "path": "01/75/6fa1e73a8fda67c02da29189541be78577c8535ea7b721e4c5c3b62a7fcc/luigi-1.0.9.tar.gz",
+ "size": 228183
+ }
+ ],
+ "1.0.7": [
+ {
+ "has_sig": false,
+ "upload_time": "2013-08-08T00:03:23",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/2b/e1/551931e19ff0aa49489be78f471bfaaed6c5ae2da4b368c3fb4ccc3293ff/luigi-1.0.7.tar.gz",
+ "md5_digest": "38b4c984f1d3e702115a697d1637878c",
+ "downloads": 2184,
+ "filename": "luigi-1.0.7.tar.gz",
+ "packagetype": "sdist",
+ "path": "2b/e1/551931e19ff0aa49489be78f471bfaaed6c5ae2da4b368c3fb4ccc3293ff/luigi-1.0.7.tar.gz",
+ "size": 226592
+ }
+ ],
+ "2.2.0": [
+ {
+ "has_sig": false,
+ "upload_time": "2016-07-08T10:53:59",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/ab/f2/487cc0a14227f92d18291ea85bed2acbe09e23b717f42626af13f8a91fbe/luigi-2.2.0.tar.gz",
+ "md5_digest": "9e304df7d11dc54b5cc702ccd59f0012",
+ "downloads": 7715,
+ "filename": "luigi-2.2.0.tar.gz",
+ "packagetype": "sdist",
+ "path": "ab/f2/487cc0a14227f92d18291ea85bed2acbe09e23b717f42626af13f8a91fbe/luigi-2.2.0.tar.gz",
+ "size": 1098276
+ }
+ ],
+ "1.0": [
+ {
+ "has_sig": false,
+ "upload_time": "2012-10-21T18:51:38",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/fd/e9/cf3edb46c2be2d5f6e1cb345af929e5240473c310a1a004d42aa1c69e718/luigi-1.0.tar.gz",
+ "md5_digest": "eef9f05d7b9930943c6f631253a90cf6",
+ "downloads": 2664,
+ "filename": "luigi-1.0.tar.gz",
+ "packagetype": "sdist",
+ "path": "fd/e9/cf3edb46c2be2d5f6e1cb345af929e5240473c310a1a004d42aa1c69e718/luigi-1.0.tar.gz",
+ "size": 64636
+ }
+ ],
+ "2.1.0": [
+ {
+ "has_sig": false,
+ "upload_time": "2016-04-01T22:30:41",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/3b/e8/1935ca0d61e89c135b06e27ebeb39e819d73cd162f8b8fabb3cb62fe4852/luigi-2.1.0.tar.gz",
+ "md5_digest": "1f2b1e7de7a17d025163cff8d05f7a7a",
+ "downloads": 328,
+ "filename": "luigi-2.1.0.tar.gz",
+ "packagetype": "sdist",
+ "path": "3b/e8/1935ca0d61e89c135b06e27ebeb39e819d73cd162f8b8fabb3cb62fe4852/luigi-2.1.0.tar.gz",
+ "size": 1122512
+ }
+ ],
+ "2.1.1": [
+ {
+ "has_sig": false,
+ "upload_time": "2016-04-06T07:17:35",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/47/ef/50c8d8b71b6613bb17088cf7b02319dd907d8bd05f6280e27a4199c68402/luigi-2.1.1.tar.gz",
+ "md5_digest": "f05aab98f4212d807b5ab348239058ec",
+ "downloads": 24120,
+ "filename": "luigi-2.1.1.tar.gz",
+ "packagetype": "sdist",
+ "path": "47/ef/50c8d8b71b6613bb17088cf7b02319dd907d8bd05f6280e27a4199c68402/luigi-2.1.1.tar.gz",
+ "size": 1129059
+ }
+ ],
+ "1.0.2": [
+ {
+ "has_sig": false,
+ "upload_time": "2013-04-25T17:18:57",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/9a/d5/6351a5b71f2bb6501211f6fc3d5e102d72017ef289b6729610208765617f/luigi-1.0.2.tar.gz",
+ "md5_digest": "9ef8a6a5783f0bd5dbdbe4b8a889bb84",
+ "downloads": 2215,
+ "filename": "luigi-1.0.2.tar.gz",
+ "packagetype": "sdist",
+ "path": "9a/d5/6351a5b71f2bb6501211f6fc3d5e102d72017ef289b6729610208765617f/luigi-1.0.2.tar.gz",
+ "size": 78573
+ }
+ ],
+ "1.0.3": [
+ {
+ "has_sig": false,
+ "upload_time": "2013-04-25T17:20:20",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/d6/8a/d9bd49a8ce0cb8e5e26f35436e5dafab01bb4fb13d7189a59f95b52a8a7b/luigi-1.0.3.tar.gz",
+ "md5_digest": "8fb2043ccf28c6034c3b2e1c8b0a92ff",
+ "downloads": 10655,
+ "filename": "luigi-1.0.3.tar.gz",
+ "packagetype": "sdist",
+ "path": "d6/8a/d9bd49a8ce0cb8e5e26f35436e5dafab01bb4fb13d7189a59f95b52a8a7b/luigi-1.0.3.tar.gz",
+ "size": 93196
+ }
+ ],
+ "1.0.16": [
+ {
+ "has_sig": false,
+ "upload_time": "2014-05-17T16:34:18",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/be/43/d9c21e162f3412833ab57d8fb22e328dbfec9e68e562e09e612f8bb8afd0/luigi-1.0.16.tar.gz",
+ "md5_digest": "edbebf80d6c332fcd07907c14da4d326",
+ "downloads": 30433,
+ "filename": "luigi-1.0.16.tar.gz",
+ "packagetype": "sdist",
+ "path": "be/43/d9c21e162f3412833ab57d8fb22e328dbfec9e68e562e09e612f8bb8afd0/luigi-1.0.16.tar.gz",
+ "size": 277787
+ }
+ ],
+ "1.0.17": [
+ {
+ "has_sig": false,
+ "upload_time": "2014-08-26T14:32:35",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/ba/f5/b3d877f760ae4cd741ba90ca4b0fcf0527b1e7e72ec34d13a8762afbdbc0/luigi-1.0.17.tar.gz",
+ "md5_digest": "13151df79c743df21358560f0e7e9321",
+ "downloads": 3871,
+ "filename": "luigi-1.0.17.tar.gz",
+ "packagetype": "sdist",
+ "path": "ba/f5/b3d877f760ae4cd741ba90ca4b0fcf0527b1e7e72ec34d13a8762afbdbc0/luigi-1.0.17.tar.gz",
+ "size": 296199
+ }
+ ],
+ "1.0.14": [
+ {
+ "has_sig": false,
+ "upload_time": "2014-05-14T11:56:59",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/31/7a/697567f198c3187d329bd5239380595c18b1d4cec2100abb8683a5431449/luigi-1.0.14.tar.gz",
+ "md5_digest": "f9212f6cd1dc046739664b5bedcc3415",
+ "downloads": 1802,
+ "filename": "luigi-1.0.14.tar.gz",
+ "packagetype": "sdist",
+ "path": "31/7a/697567f198c3187d329bd5239380595c18b1d4cec2100abb8683a5431449/luigi-1.0.14.tar.gz",
+ "size": 277355
+ }
+ ],
+ "1.0.15": [
+ {
+ "has_sig": false,
+ "upload_time": "2014-05-14T14:18:30",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/e9/a4/229f2ba9f070bb167249989c872b1e6bd84afcaba5aa14d16f913e2a3388/luigi-1.0.15.tar.gz",
+ "md5_digest": "7222e00a048b66d6e92af253fc86810b",
+ "downloads": 1949,
+ "filename": "luigi-1.0.15.tar.gz",
+ "packagetype": "sdist",
+ "path": "e9/a4/229f2ba9f070bb167249989c872b1e6bd84afcaba5aa14d16f913e2a3388/luigi-1.0.15.tar.gz",
+ "size": 277722
+ }
+ ],
+ "1.0.12": [
+ {
+ "has_sig": false,
+ "upload_time": "2013-11-26T04:18:10",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/5a/09/38185b73e7ea6d477ea01cc85f075b77730595b1f8b0e55a4edbeac66d53/luigi-1.0.12.tar.gz",
+ "md5_digest": "58d33b2f940bd4ad2baa5281d4240345",
+ "downloads": 18087,
+ "filename": "luigi-1.0.12.tar.gz",
+ "packagetype": "sdist",
+ "path": "5a/09/38185b73e7ea6d477ea01cc85f075b77730595b1f8b0e55a4edbeac66d53/luigi-1.0.12.tar.gz",
+ "size": 238722
+ }
+ ],
+ "1.0.13": [
+ {
+ "has_sig": false,
+ "upload_time": "2014-02-03T05:44:54",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/bb/d8/ec43a5bbbf963675a198dd0c050f61df859c326b9373d26ac22bee00aa95/luigi-1.0.13.tar.gz",
+ "md5_digest": "3150d20f66026df00887625f11720acb",
+ "downloads": 5096,
+ "filename": "luigi-1.0.13.tar.gz",
+ "packagetype": "sdist",
+ "path": "bb/d8/ec43a5bbbf963675a198dd0c050f61df859c326b9373d26ac22bee00aa95/luigi-1.0.13.tar.gz",
+ "size": 293454
+ }
+ ],
+ "1.0.10": [
+ {
+ "has_sig": false,
+ "upload_time": "2013-08-09T16:06:37",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/07/c1/26b984d5f1084e57ff9207a9b1873ce0a0c3d4c1c857f20fa38e93c45b3b/luigi-1.0.10.tar.gz",
+ "md5_digest": "7f6a390a7d928f3866f13bd5be55a91d",
+ "downloads": 4379,
+ "filename": "luigi-1.0.10.tar.gz",
+ "packagetype": "sdist",
+ "path": "07/c1/26b984d5f1084e57ff9207a9b1873ce0a0c3d4c1c857f20fa38e93c45b3b/luigi-1.0.10.tar.gz",
+ "size": 228201
+ }
+ ],
+ "1.0.11": [
+ {
+ "has_sig": false,
+ "upload_time": "2013-11-21T23:07:21",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/bd/f4/8828fbced3792398065560a5d7203df45b85199f230bde9364d9ce37726e/luigi-1.0.11.tar.gz",
+ "md5_digest": "d5858aeeb5deef91ae819376ebefd83d",
+ "downloads": 2062,
+ "filename": "luigi-1.0.11.tar.gz",
+ "packagetype": "sdist",
+ "path": "bd/f4/8828fbced3792398065560a5d7203df45b85199f230bde9364d9ce37726e/luigi-1.0.11.tar.gz",
+ "size": 238741
+ }
+ ],
+ "1.0.18": [
+ {
+ "has_sig": false,
+ "upload_time": "2014-09-15T11:40:39",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/0b/9a/f51f96ca7ee9a330d6912d08c5fe237008de1c10c52114722f68d15bdee8/luigi-1.0.18.tar.gz",
+ "md5_digest": "e7cda3de5128d697ecb89b126522aa21",
+ "downloads": 2150,
+ "filename": "luigi-1.0.18.tar.gz",
+ "packagetype": "sdist",
+ "path": "0b/9a/f51f96ca7ee9a330d6912d08c5fe237008de1c10c52114722f68d15bdee8/luigi-1.0.18.tar.gz",
+ "size": 297983
+ }
+ ],
+ "1.0.19": [
+ {
+ "has_sig": false,
+ "upload_time": "2014-09-22T12:14:38",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/f5/a2/ee698ff0e301b321ffccf0a254df5e30e5ab734d23886606937f73b5ccb6/luigi-1.0.19.tar.gz",
+ "md5_digest": "3170554e32a7a630f9457d3298741538",
+ "downloads": 207006,
+ "filename": "luigi-1.0.19.tar.gz",
+ "packagetype": "sdist",
+ "path": "f5/a2/ee698ff0e301b321ffccf0a254df5e30e5ab734d23886606937f73b5ccb6/luigi-1.0.19.tar.gz",
+ "size": 300167
+ }
+ ],
+ "2.3.0": [
+ {
+ "has_sig": false,
+ "upload_time": "2016-08-12T03:20:41",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/25/64/5383d94b5b44e9c1443c1a6b857210ace8205954359f8353a50c16deb664/luigi-2.3.0.tar.gz",
+ "md5_digest": "3b7e0b4c8d684a168c97a4fb2d9340ca",
+ "downloads": 1188,
+ "filename": "luigi-2.3.0.tar.gz",
+ "packagetype": "sdist",
+ "path": "25/64/5383d94b5b44e9c1443c1a6b857210ace8205954359f8353a50c16deb664/luigi-2.3.0.tar.gz",
+ "size": 1113879
+ }
+ ],
+ "2.3.1": [
+ {
+ "has_sig": false,
+ "upload_time": "2016-08-25T02:41:26",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/55/8d/0842fbdb05a18d4a9e578f7c1661fbc719c625b1d1f0f9ceb08ea8bea518/luigi-2.3.1.tar.gz",
+ "md5_digest": "e48786e9ac71d8fd58694529d3f5539d",
+ "downloads": 7557,
+ "filename": "luigi-2.3.1.tar.gz",
+ "packagetype": "sdist",
+ "path": "55/8d/0842fbdb05a18d4a9e578f7c1661fbc719c625b1d1f0f9ceb08ea8bea518/luigi-2.3.1.tar.gz",
+ "size": 1114644
+ }
+ ],
+ "2.3.2": [
+ {
+ "has_sig": false,
+ "upload_time": "2016-09-20T09:46:25",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/d5/0b/531d2efe721a7195bd593ff2d92d41720b10dae0093f9abfd2c073560dcf/luigi-2.3.2.tar.gz",
+ "md5_digest": "cd622f6fbae981bc1b8f9b0132b189b8",
+ "downloads": 8558,
+ "filename": "luigi-2.3.2.tar.gz",
+ "packagetype": "sdist",
+ "path": "d5/0b/531d2efe721a7195bd593ff2d92d41720b10dae0093f9abfd2c073560dcf/luigi-2.3.2.tar.gz",
+ "size": 1116310
+ }
+ ],
+ "2.3.3": [
+ {
+ "has_sig": false,
+ "upload_time": "2016-10-21T04:04:56",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/80/83/f1f805266ba83964b90e31890d8f8f9ee4b82c40e9778fac350bdf830fba/luigi-2.3.3.tar.gz",
+ "md5_digest": "dea3b1cb636f7ac141c6054717728830",
+ "downloads": 7910,
+ "filename": "luigi-2.3.3.tar.gz",
+ "packagetype": "sdist",
+ "path": "80/83/f1f805266ba83964b90e31890d8f8f9ee4b82c40e9778fac350bdf830fba/luigi-2.3.3.tar.gz",
+ "size": 1119561
+ }
+ ],
+ "1.3.0": [
+ {
+ "has_sig": false,
+ "upload_time": "2015-06-26T13:19:38",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/7a/3d/da7ebf732a295098ec7b72aefd6580cc68dad461fdbce9265ddb8a3544f8/luigi-1.3.0.tar.gz",
+ "md5_digest": "948a6574e4d4e1d1d8b8a355ca0cdaf7",
+ "downloads": 44182,
+ "filename": "luigi-1.3.0.tar.gz",
+ "packagetype": "sdist",
+ "path": "7a/3d/da7ebf732a295098ec7b72aefd6580cc68dad461fdbce9265ddb8a3544f8/luigi-1.3.0.tar.gz",
+ "size": 457934
+ }
+ ],
+ "1.2.1": [
+ {
+ "has_sig": false,
+ "upload_time": "2015-05-26T10:00:32",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/3f/c7/7f5e1f5016a23c6cf2b3152bd27d994ad3b384e59e3c1bfdec444669853d/luigi-1.2.1.tar.gz",
+ "md5_digest": "a147bba0bb1999b5856f4910bf15a9c0",
+ "downloads": 25856,
+ "filename": "luigi-1.2.1.tar.gz",
+ "packagetype": "sdist",
+ "path": "3f/c7/7f5e1f5016a23c6cf2b3152bd27d994ad3b384e59e3c1bfdec444669853d/luigi-1.2.1.tar.gz",
+ "size": 449107
+ }
+ ],
+ "2.4.0": [
+ {
+ "has_sig": false,
+ "upload_time": "2016-12-02T04:52:12",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/6a/84/42bea7839bc6eee8c219775f6afe3e296a554985a0aa216fb6090478a3e5/luigi-2.4.0.tar.gz",
+ "md5_digest": "76303fa7281ac0c6a95aa9ada13acc3e",
+ "downloads": 5965,
+ "filename": "luigi-2.4.0.tar.gz",
+ "packagetype": "sdist",
+ "path": "6a/84/42bea7839bc6eee8c219775f6afe3e296a554985a0aa216fb6090478a3e5/luigi-2.4.0.tar.gz",
+ "size": 1128461
+ }
+ ],
+ "2.5.0": [
+ {
+ "has_sig": false,
+ "upload_time": "2017-01-10T07:54:38",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/9a/f2/7f7bf85e1e380375cc8a291ed648c733b4f310fe43a00073fff12bb61692/luigi-2.5.0.tar.gz",
+ "md5_digest": "26c29cd4d18381b1f148a7a43cbee335",
+ "downloads": 0,
+ "filename": "luigi-2.5.0.tar.gz",
+ "packagetype": "sdist",
+ "path": "9a/f2/7f7bf85e1e380375cc8a291ed648c733b4f310fe43a00073fff12bb61692/luigi-2.5.0.tar.gz",
+ "size": 1130701
+ }
+ ],
+ "1.0.4": [
+ {
+ "has_sig": false,
+ "upload_time": "2013-08-07T18:46:38",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/56/09/d3776490559b62d53b7cf87cb066b76b9a7f91d6749325d146c76a2adc42/luigi-1.0.4.tar.gz",
+ "md5_digest": "d5eef08fb8f76875bc28680ec72511f8",
+ "downloads": 2175,
+ "filename": "luigi-1.0.4.tar.gz",
+ "packagetype": "sdist",
+ "path": "56/09/d3776490559b62d53b7cf87cb066b76b9a7f91d6749325d146c76a2adc42/luigi-1.0.4.tar.gz",
+ "size": 71168
+ }
+ ],
+ "2.6.0.beta1": [
+ {
+ "has_sig": false,
+ "upload_time": "2017-02-10T06:57:18",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/9f/aa/5067601c565d61c8e1f172035eee4f1d50f25a193b9041f17ebc6fff5764/luigi-2.6.0.beta1.tar.gz",
+ "md5_digest": "8c36cf3d37525ccc57f6ecc24431bdef",
+ "downloads": 0,
+ "filename": "luigi-2.6.0.beta1.tar.gz",
+ "packagetype": "sdist",
+ "path": "9f/aa/5067601c565d61c8e1f172035eee4f1d50f25a193b9041f17ebc6fff5764/luigi-2.6.0.beta1.tar.gz",
+ "size": 1158747
+ }
+ ],
+ "1.0.24": [
+ {
+ "has_sig": false,
+ "upload_time": "2015-02-11T12:01:07",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/3c/a5/3bc272eb6317147ddaf8c0c3bf7ba47a684216f5e16c4fdf80f05ac94d60/luigi-1.0.24.tar.gz",
+ "md5_digest": "44c6f413dff37e6cd295e696f2cdea19",
+ "downloads": 23418,
+ "filename": "luigi-1.0.24.tar.gz",
+ "packagetype": "sdist",
+ "path": "3c/a5/3bc272eb6317147ddaf8c0c3bf7ba47a684216f5e16c4fdf80f05ac94d60/luigi-1.0.24.tar.gz",
+ "size": 333339
+ }
+ ],
+ "1.0.23": [
+ {
+ "has_sig": false,
+ "upload_time": "2015-02-10T11:53:49",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/2e/5c/d53458d78415079fef6bc2231f7b5f5e5876e90f39cc2c57a054379df0cc/luigi-1.0.23.tar.gz",
+ "md5_digest": "0c9d7dd091b913f9076b5517dc41cd91",
+ "downloads": 2542,
+ "filename": "luigi-1.0.23.tar.gz",
+ "packagetype": "sdist",
+ "path": "2e/5c/d53458d78415079fef6bc2231f7b5f5e5876e90f39cc2c57a054379df0cc/luigi-1.0.23.tar.gz",
+ "size": 333182
+ }
+ ],
+ "1.0.22": [
+ {
+ "has_sig": false,
+ "upload_time": "2015-02-10T04:20:16",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/b7/8b/d7751ae52e30e1b872bcaaf4626b202e0fc61c2c91fef91912b6e901545e/luigi-1.0.22.tar.gz",
+ "md5_digest": "10762c7d1999babdb38471a26b1d2880",
+ "downloads": 1072,
+ "filename": "luigi-1.0.22.tar.gz",
+ "packagetype": "sdist",
+ "path": "b7/8b/d7751ae52e30e1b872bcaaf4626b202e0fc61c2c91fef91912b6e901545e/luigi-1.0.22.tar.gz",
+ "size": 333175
+ }
+ ],
+ "1.0.21": [],
+ "1.0.20": [
+ {
+ "has_sig": false,
+ "upload_time": "2015-01-21T16:27:35",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/2b/88/804830f0c78ebe1a2b1dfbf723bfcd97f6822f4e139da5909cd87baf2374/luigi-1.0.20.tar.gz",
+ "md5_digest": "f1edc408bb19ffaf18a88693abc0d765",
+ "downloads": 6245,
+ "filename": "luigi-1.0.20.tar.gz",
+ "packagetype": "sdist",
+ "path": "2b/88/804830f0c78ebe1a2b1dfbf723bfcd97f6822f4e139da5909cd87baf2374/luigi-1.0.20.tar.gz",
+ "size": 324700
+ }
+ ]
+ },
+ "urls": [
+ {
+ "has_sig": false,
+ "upload_time": "2017-02-10T06:57:18",
+ "comment_text": "",
+ "python_version": "source",
+ "url": "https://pypi.org/packages/9f/aa/5067601c565d61c8e1f172035eee4f1d50f25a193b9041f17ebc6fff5764/luigi-2.6.0.beta1.tar.gz",
+ "md5_digest": "8c36cf3d37525ccc57f6ecc24431bdef",
+ "downloads": 0,
+ "filename": "luigi-2.6.0.beta1.tar.gz",
+ "packagetype": "sdist",
+ "path": "9f/aa/5067601c565d61c8e1f172035eee4f1d50f25a193b9041f17ebc6fff5764/luigi-2.6.0.beta1.tar.gz",
+ "size": 1158747
+ }
+ ]
+}
diff --git a/uv/spec/fixtures/pypi/pypi_response_project_urls_source.json b/uv/spec/fixtures/pypi/pypi_response_project_urls_source.json
new file mode 100644
index 00000000000..b6732a80ea2
--- /dev/null
+++ b/uv/spec/fixtures/pypi/pypi_response_project_urls_source.json
@@ -0,0 +1,180 @@
+{
+ "info": {
+ "bugtrack_url": null,
+ "classifiers": [
+ "Development Status :: 5 - Production/Stable",
+ "Environment :: Web Environment",
+ "Framework :: Django",
+ "Framework :: Django :: 3.2",
+ "Intended Audience :: Developers",
+ "License :: OSI Approved :: BSD License",
+ "Operating System :: OS Independent",
+ "Programming Language :: Python :: 3",
+ "Programming Language :: Python :: 3.10"
+ ],
+ "description": null,
+ "docs_url": null,
+ "download_url": null,
+ "downloads": {
+ "last_day": -1,
+ "last_month": -1,
+ "last_week": -1
+ },
+ "dynamic": null,
+ "home_page": "https://django-split-settings.readthedocs.io",
+ "keywords": "django, settings, configuration, config",
+ "name": "django-split-settings",
+ "package_url": "https://pypi.org/project/django-split-settings/",
+ "platform": null,
+ "project_url": "https://pypi.org/project/django-split-settings/",
+ "project_urls": {
+ "Funding": "https://github.com/sponsors/xxxxx",
+ "Homepage": "https://django-split-settings.readthedocs.io",
+ "Repository": "https://github.com/xxxxx/django-split-settings"
+ },
+ "provides_extra": null,
+ "release_url": "https://pypi.org/project/django-split-settings/1.3.2/",
+ "requires_dist": null,
+ "requires_python": "<4.0,>=3.9",
+ "summary": "Organize Django settings into multiple files and directories.",
+ "version": "1.3.2",
+ "yanked": false,
+ "yanked_reason": null
+ },
+ "last_serial": 24000635,
+ "releases": {
+ "1.3.1": [
+ {
+ "comment_text": "",
+ "digests": {
+ "blake2b_256": "378c6bc9468e4715016883997090a303c3b2dc08a9cf2616360e7dd53ebe839b",
+ "md5": "3dea0ef804dc9bdf835b62aa2312a07c",
+ "sha256": "c902ef60d5fe8190ff224284f68e3c9015b6f1aca9e9d6bd70bf86394ff32634"
+ },
+ "downloads": -1,
+ "filename": "django_split_settings-1.3.1-py3-none-any.whl",
+ "has_sig": false,
+ "md5_digest": "3dea0ef804dc9bdf835b62aa2312a07c",
+ "packagetype": "bdist_wheel",
+ "python_version": "py3",
+ "requires_python": "<4.0,>=3.9",
+ "size": 6407,
+ "upload_time": "2024-04-05T07:14:12",
+ "upload_time_iso_8601": "2024-04-05T07:14:12.246439Z",
+ "url": "https://files.pythonhosted.org/packages/37/8c/6bc9468e4715016883997090a303c3b2dc08a9cf2616360e7dd53ebe839b/django_split_settings-1.3.1-py3-none-any.whl",
+ "yanked": false,
+ "yanked_reason": null
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "blake2b_256": "cb20400c2094d5db8aed83fb10634d072dc36ae35142425d56d602e11309d589",
+ "md5": "ec0644f368c12606faa743630eb73d9d",
+ "sha256": "c1f57f6b54fc0d93082c12163e76fad082c214f5fa0d16d84a1226d2c9f14f26"
+ },
+ "downloads": -1,
+ "filename": "django_split_settings-1.3.1.tar.gz",
+ "has_sig": false,
+ "md5_digest": "ec0644f368c12606faa743630eb73d9d",
+ "packagetype": "sdist",
+ "python_version": "source",
+ "requires_python": "<4.0,>=3.9",
+ "size": 5723,
+ "upload_time": "2024-04-05T07:14:14",
+ "upload_time_iso_8601": "2024-04-05T07:14:14.101556Z",
+ "url": "https://files.pythonhosted.org/packages/cb/20/400c2094d5db8aed83fb10634d072dc36ae35142425d56d602e11309d589/django_split_settings-1.3.1.tar.gz",
+ "yanked": false,
+ "yanked_reason": null
+ }
+ ],
+ "1.3.2": [
+ {
+ "comment_text": "",
+ "digests": {
+ "blake2b_256": "6369d94db8dac55bcfb6b3243578a3096cfda6c42ea5da292c36919768152ec6",
+ "md5": "c06d6d4bf3b8dc83e295fd86dc2e4e13",
+ "sha256": "72bd7dd9f12602585681074d1f859643fb4f6b196b584688fab86bdd73a57dff"
+ },
+ "downloads": -1,
+ "filename": "django_split_settings-1.3.2-py3-none-any.whl",
+ "has_sig": false,
+ "md5_digest": "c06d6d4bf3b8dc83e295fd86dc2e4e13",
+ "packagetype": "bdist_wheel",
+ "python_version": "py3",
+ "requires_python": "<4.0,>=3.9",
+ "size": 6435,
+ "upload_time": "2024-07-05T14:29:59",
+ "upload_time_iso_8601": "2024-07-05T14:29:59.756365Z",
+ "url": "https://files.pythonhosted.org/packages/63/69/d94db8dac55bcfb6b3243578a3096cfda6c42ea5da292c36919768152ec6/django_split_settings-1.3.2-py3-none-any.whl",
+ "yanked": false,
+ "yanked_reason": null
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "blake2b_256": "deb91c13089454afd7a42d492b8aa8a0c7e49eeca58c0f2ad331f361a067c876",
+ "md5": "a51b6266e7aa2307ba213c7c14188d69",
+ "sha256": "d3975aa3601e37f65c59b9977b6bcb1de8bc27496930054078589c7d56998a9d"
+ },
+ "downloads": -1,
+ "filename": "django_split_settings-1.3.2.tar.gz",
+ "has_sig": false,
+ "md5_digest": "a51b6266e7aa2307ba213c7c14188d69",
+ "packagetype": "sdist",
+ "python_version": "source",
+ "requires_python": "<4.0,>=3.9",
+ "size": 5751,
+ "upload_time": "2024-07-05T14:30:05",
+ "upload_time_iso_8601": "2024-07-05T14:30:05.997090Z",
+ "url": "https://files.pythonhosted.org/packages/de/b9/1c13089454afd7a42d492b8aa8a0c7e49eeca58c0f2ad331f361a067c876/django_split_settings-1.3.2.tar.gz",
+ "yanked": false,
+ "yanked_reason": null
+ }
+ ]
+ },
+ "urls": [
+ {
+ "comment_text": "",
+ "digests": {
+ "blake2b_256": "6369d94db8dac55bcfb6b3243578a3096cfda6c42ea5da292c36919768152ec6",
+ "md5": "c06d6d4bf3b8dc83e295fd86dc2e4e13",
+ "sha256": "72bd7dd9f12602585681074d1f859643fb4f6b196b584688fab86bdd73a57dff"
+ },
+ "downloads": -1,
+ "filename": "django_split_settings-1.3.2-py3-none-any.whl",
+ "has_sig": false,
+ "md5_digest": "c06d6d4bf3b8dc83e295fd86dc2e4e13",
+ "packagetype": "bdist_wheel",
+ "python_version": "py3",
+ "requires_python": "<4.0,>=3.9",
+ "size": 6435,
+ "upload_time": "2024-07-05T14:29:59",
+ "upload_time_iso_8601": "2024-07-05T14:29:59.756365Z",
+ "url": "https://files.pythonhosted.org/packages/63/69/d94db8dac55bcfb6b3243578a3096cfda6c42ea5da292c36919768152ec6/django_split_settings-1.3.2-py3-none-any.whl",
+ "yanked": false,
+ "yanked_reason": null
+ },
+ {
+ "comment_text": "",
+ "digests": {
+ "blake2b_256": "deb91c13089454afd7a42d492b8aa8a0c7e49eeca58c0f2ad331f361a067c876",
+ "md5": "a51b6266e7aa2307ba213c7c14188d69",
+ "sha256": "d3975aa3601e37f65c59b9977b6bcb1de8bc27496930054078589c7d56998a9d"
+ },
+ "downloads": -1,
+ "filename": "django_split_settings-1.3.2.tar.gz",
+ "has_sig": false,
+ "md5_digest": "a51b6266e7aa2307ba213c7c14188d69",
+ "packagetype": "sdist",
+ "python_version": "source",
+ "requires_python": "<4.0,>=3.9",
+ "size": 5751,
+ "upload_time": "2024-07-05T14:30:05",
+ "upload_time_iso_8601": "2024-07-05T14:30:05.997090Z",
+ "url": "https://files.pythonhosted.org/packages/de/b9/1c13089454afd7a42d492b8aa8a0c7e49eeca58c0f2ad331f361a067c876/django_split_settings-1.3.2.tar.gz",
+ "yanked": false,
+ "yanked_reason": null
+ }
+ ],
+ "vulnerabilities": []
+}
diff --git a/uv/spec/fixtures/pypi/pypi_simple_response.html b/uv/spec/fixtures/pypi/pypi_simple_response.html
new file mode 100644
index 00000000000..772fe2e6c5c
--- /dev/null
+++ b/uv/spec/fixtures/pypi/pypi_simple_response.html
@@ -0,0 +1,93 @@
+
+
+
+ Links for luigi
+
+
+ Links for luigi
+ luigi-1.0.9.tar.gz
+
+ luigi-1.0.10.tar.gz
+
+ luigi-1.0.18.tar.gz
+
+ luigi-2.3.0.tar.gz
+
+ luigi-1.0.20.tar.gz
+
+ luigi-1.0.7.tar.gz
+
+ luigi-1.0.23.tar.gz
+
+ luigi-1.0.14.tar.gz
+
+ luigi-2.1.0.tar.gz
+
+ luigi-1.0.24.tar.gz
+
+ luigi-1.1.2.tar.gz
+
+ luigi-1.2.1.tar.gz
+
+ luigi-2.1.1.tar.gz
+
+ luigi-2.7.0b1.tar.gz
+
+ luigi-2.3.1.tar.gz
+
+ luigi-1.0.4.tar.gz
+
+ luigi-1.1.1.tar.gz
+
+ luigi-1.0.12.tar.gz
+
+ luigi-2.4.0.tar.gz
+
+ luigi-1.3.0.tar.gz
+
+ luigi-2.3.3.tar.gz
+
+ luigi-1.1.0.tar.gz
+
+ luigi-1.0.5.tar.gz
+
+ luigi-1.0.2.tar.gz
+
+ luigi-2.5.0.tar.gz
+
+ luigi-2.6.0.tar.gz
+
+ luigi-1.0.1.tar.gz
+
+ luigi-2.2.0.tar.gz
+
+ luigi-1.0.9.macosx-10.7-intel.tar.gz
+
+ luigi-1.0.22.tar.gz
+
+ luigi-1.0.17.tar.gz
+
+ luigi-1.0.13.tar.gz
+
+ luigi-1.0.11.tar.gz
+
+ luigi-1.0.16.tar.gz
+
+ luigi-2.0.1.tar.gz
+
+ luigi-2.3.2.tar.gz
+
+ luigi-1.0.3.tar.gz
+
+ luigi-1.0.6.tar.gz
+
+ luigi-1.0.15.tar.gz
+
+ luigi-1.0.19.tar.gz
+
+ luigi-2.0.0.tar.gz
+
+ luigi-1.0.tar.gz
+
+
+
diff --git a/uv/spec/fixtures/pypi/pypi_simple_response_attrs.html b/uv/spec/fixtures/pypi/pypi_simple_response_attrs.html
new file mode 100644
index 00000000000..75937c17408
--- /dev/null
+++ b/uv/spec/fixtures/pypi/pypi_simple_response_attrs.html
@@ -0,0 +1,40 @@
+
+
+
+ Links for attrs
+
+
+ Links for attrs
+ attrs-15.0.0a1-py2-none-any.whl
+ attrs-15.0.0a1.tar.gz
+ attrs-15.0.0-py2-none-any.whl
+ attrs-15.0.0.tar.gz
+ attrs-15.1.0-py2.py3-none-any.whl
+ attrs-15.1.0.tar.gz
+ attrs-15.2.0-py2.py3-none-any.whl
+ attrs-15.2.0.tar.gz
+ attrs-16.0.0-py2.py3-none-any.whl
+ attrs-16.0.0.tar.gz
+ attrs-16.1.0-py2.py3-none-any.whl
+ attrs-16.1.0.tar.gz
+ attrs-16.2.0-py2.py3-none-any.whl
+ attrs-16.2.0.tar.gz
+ attrs-16.3.0-py2.py3-none-any.whl
+ attrs-16.3.0.tar.gz
+ attrs-17.1.0-py2.py3-none-any.whl
+ attrs-17.1.0.tar.gz
+ attrs-17.2.0-py2.py3-none-any.whl
+ attrs-17.2.0.tar.gz
+ attrs-17.3.0-py2.py3-none-any.whl
+ attrs-17.3.0.tar.gz
+ attrs-17.4.0-py2.py3-none-any.whl
+ attrs-17.4.0.tar.gz
+ attrs-18.1.0-py2.py3-none-any.whl
+ attrs-18.1.0.tar.gz
+ attrs-18.2.0-py2.py3-none-any.whl
+ attrs-18.2.0.tar.gz
+ attrs-19.1.0-py2.py3-none-any.whl
+ attrs-19.1.0.tar.gz
+
+
+
\ No newline at end of file
diff --git a/uv/spec/fixtures/pypi/pypi_simple_response_capital.html b/uv/spec/fixtures/pypi/pypi_simple_response_capital.html
new file mode 100644
index 00000000000..9a6a7be7fa7
--- /dev/null
+++ b/uv/spec/fixtures/pypi/pypi_simple_response_capital.html
@@ -0,0 +1,93 @@
+
+
+
+ Links for luigi
+
+
+ Links for luigi
+ Luigi-1.0.9.tar.gz
+
+ Luigi-1.0.10.tar.gz
+
+ Luigi-1.0.18.tar.gz
+
+ Luigi-2.3.0.tar.gz
+
+ Luigi-1.0.20.tar.gz
+
+ Luigi-1.0.7.tar.gz
+
+ Luigi-1.0.23.tar.gz
+
+ Luigi-1.0.14.tar.gz
+
+ Luigi-2.1.0.tar.gz
+
+ Luigi-1.0.24.tar.gz
+
+ Luigi-1.1.2.tar.gz
+
+ Luigi-1.2.1.tar.gz
+
+ Luigi-2.1.1.tar.gz
+
+ Luigi-2.7.0b1.tar.gz
+
+ Luigi-2.3.1.tar.gz
+
+ Luigi-1.0.4.tar.gz
+
+ Luigi-1.1.1.tar.gz
+
+ Luigi-1.0.12.tar.gz
+
+ Luigi-2.4.0.tar.gz
+
+ Luigi-1.3.0.tar.gz
+
+ Luigi-2.3.3.tar.gz
+
+ Luigi-1.1.0.tar.gz
+
+ Luigi-1.0.5.tar.gz
+
+ Luigi-1.0.2.tar.gz
+
+ Luigi-2.5.0.tar.gz
+
+ Luigi-2.6.0.tar.gz
+
+ Luigi-1.0.1.tar.gz
+
+ Luigi-2.2.0.tar.gz
+
+ Luigi-1.0.9.macosx-10.7-intel.tar.gz
+
+ Luigi-1.0.22.tar.gz
+
+ Luigi-1.0.17.tar.gz
+
+ Luigi-1.0.13.tar.gz
+
+ Luigi-1.0.11.tar.gz
+
+ Luigi-1.0.16.tar.gz
+
+ Luigi-2.0.1.tar.gz
+
+ Luigi-2.3.2.tar.gz
+
+ Luigi-1.0.3.tar.gz
+
+ Luigi-1.0.6.tar.gz
+
+ Luigi-1.0.15.tar.gz
+
+ Luigi-1.0.19.tar.gz
+
+ Luigi-2.0.0.tar.gz
+
+ Luigi-1.0.tar.gz
+
+
+
diff --git a/uv/spec/fixtures/pypi/pypi_simple_response_devpi.html b/uv/spec/fixtures/pypi/pypi_simple_response_devpi.html
new file mode 100644
index 00000000000..fff600046b1
--- /dev/null
+++ b/uv/spec/fixtures/pypi/pypi_simple_response_devpi.html
@@ -0,0 +1,378 @@
+
+
+
+ root/edge/: luigi versions
+
+
+
+
+
+
+
+
+
+
root/edge/: luigi versions
+
+
+
+
+
+
diff --git a/uv/spec/fixtures/pypi/pypi_simple_response_django.html b/uv/spec/fixtures/pypi/pypi_simple_response_django.html
new file mode 100644
index 00000000000..a14d2e5c3a6
--- /dev/null
+++ b/uv/spec/fixtures/pypi/pypi_simple_response_django.html
@@ -0,0 +1,480 @@
+
+
+
+
+ Links for Django
+
+
+ Links for Django
+ Django-1.1.3.tar.gz
+ Django-1.1.4.tar.gz
+ Django-1.2.tar.gz
+ Django-1.2.1.tar.gz
+ Django-1.2.2.tar.gz
+ Django-1.2.3.tar.gz
+ Django-1.2.4.tar.gz
+ Django-1.2.5.tar.gz
+ Django-1.2.6.tar.gz
+ Django-1.2.7.tar.gz
+ Django-1.3.tar.gz
+ Django-1.3.1.tar.gz
+ Django-1.3.2.tar.gz
+ Django-1.3.3.tar.gz
+ Django-1.3.4.tar.gz
+ Django-1.3.5.tar.gz
+ Django-1.3.6.tar.gz
+ Django-1.3.7.tar.gz
+ Django-1.4.tar.gz
+ Django-1.4.1.tar.gz
+ Django-1.4.2.tar.gz
+ Django-1.4.3.tar.gz
+ Django-1.4.4.tar.gz
+ Django-1.4.5.tar.gz
+ Django-1.4.6.tar.gz
+ Django-1.4.7.tar.gz
+ Django-1.4.8.tar.gz
+ Django-1.4.9.tar.gz
+ Django-1.4.10.tar.gz
+ Django-1.4.11.tar.gz
+ Django-1.4.12.tar.gz
+ Django-1.4.13.tar.gz
+ Django-1.4.14.tar.gz
+ Django-1.4.15.tar.gz
+ Django-1.4.16.tar.gz
+ Django-1.4.17.tar.gz
+ Django-1.4.18.tar.gz
+ Django-1.4.19.tar.gz
+ Django-1.4.20.tar.gz
+ Django-1.4.21.tar.gz
+ Django-1.4.22.tar.gz
+ Django-1.5.tar.gz
+ Django-1.5.1.tar.gz
+ Django-1.5.2-py2.py3-none-any.whl
+ Django-1.5.2.tar.gz
+ Django-1.5.3.tar.gz
+ Django-1.5.4.tar.gz
+ Django-1.5.5.tar.gz
+ Django-1.5.6.tar.gz
+ Django-1.5.7.tar.gz
+ Django-1.5.8-py2.py3-none-any.whl
+ Django-1.5.8.tar.gz
+ Django-1.5.9.tar.gz
+ Django-1.5.10.tar.gz
+ Django-1.5.11.tar.gz
+ Django-1.5.12-py2.py3-none-any.whl
+ Django-1.5.12.tar.gz
+ Django-1.6-py2.py3-none-any.whl
+ Django-1.6.tar.gz
+ Django-1.6.1-py2.py3-none-any.whl
+ Django-1.6.1.tar.gz
+ Django-1.6.2-py2.py3-none-any.whl
+ Django-1.6.2.tar.gz
+ Django-1.6.3-py2.py3-none-any.whl
+ Django-1.6.3.tar.gz
+ Django-1.6.4-py2.py3-none-any.whl
+ Django-1.6.4.tar.gz
+ Django-1.6.5-py2.py3-none-any.whl
+ Django-1.6.5.tar.gz
+ Django-1.6.6-py2.py3-none-any.whl
+ Django-1.6.6.tar.gz
+ Django-1.6.7-py2.py3-none-any.whl
+ Django-1.6.7.tar.gz
+ Django-1.6.8-py2.py3-none-any.whl
+ Django-1.6.8.tar.gz
+ Django-1.6.9-py2.py3-none-any.whl
+ Django-1.6.9.tar.gz
+ Django-1.6.10-py2.py3-none-any.whl
+ Django-1.6.10.tar.gz
+ Django-1.6.11-py2.py3-none-any.whl
+ Django-1.6.11.tar.gz
+ Django-1.7-py2.py3-none-any.whl
+ Django-1.7.tar.gz
+ Django-1.7.1-py2.py3-none-any.whl
+ Django-1.7.1.tar.gz
+ Django-1.7.2-py2.py3-none-any.whl
+ Django-1.7.2.tar.gz
+ Django-1.7.3-py2.py3-none-any.whl
+ Django-1.7.3.tar.gz
+ Django-1.7.4-py2.py3-none-any.whl
+ Django-1.7.4.tar.gz
+ Django-1.7.5-py2.py3-none-any.whl
+ Django-1.7.5.tar.gz
+ Django-1.7.6-py2.py3-none-any.whl
+ Django-1.7.6.tar.gz
+ Django-1.7.7-py2.py3-none-any.whl
+ Django-1.7.7.tar.gz
+ Django-1.7.8-py2.py3-none-any.whl
+ Django-1.7.8.tar.gz
+ Django-1.7.9-py2.py3-none-any.whl
+ Django-1.7.9.tar.gz
+ Django-1.7.10-py2.py3-none-any.whl
+ Django-1.7.10.tar.gz
+ Django-1.7.11-py2.py3-none-any.whl
+ Django-1.7.11.tar.gz
+ Django-1.8a1-py2.py3-none-any.whl
+ Django-1.8b1-py2.py3-none-any.whl
+ Django-1.8b2-py2.py3-none-any.whl
+ Django-1.8c1-py2.py3-none-any.whl
+ Django-1.8-py2.py3-none-any.whl
+ Django-1.8.tar.gz
+ Django-1.8.1-py2.py3-none-any.whl
+ Django-1.8.1.tar.gz
+ Django-1.8.2-py2.py3-none-any.whl
+ Django-1.8.2.tar.gz
+ Django-1.8.3-py2.py3-none-any.whl
+ Django-1.8.3.tar.gz
+ Django-1.8.4-py2.py3-none-any.whl
+ Django-1.8.4.tar.gz
+ Django-1.8.5-py2.py3-none-any.whl
+ Django-1.8.5.tar.gz
+ Django-1.8.6-py2.py3-none-any.whl
+ Django-1.8.6.tar.gz
+ Django-1.8.7-py2.py3-none-any.whl
+ Django-1.8.7.tar.gz
+ Django-1.8.8-py2.py3-none-any.whl
+ Django-1.8.8.tar.gz
+ Django-1.8.9-py2.py3-none-any.whl
+ Django-1.8.9.tar.gz
+ Django-1.8.10-py2.py3-none-any.whl
+ Django-1.8.10.tar.gz
+ Django-1.8.11-py2.py3-none-any.whl
+ Django-1.8.11.tar.gz
+ Django-1.8.12-py2.py3-none-any.whl
+ Django-1.8.12.tar.gz
+ Django-1.8.13-py2.py3-none-any.whl
+ Django-1.8.13.tar.gz
+ Django-1.8.14-py2.py3-none-any.whl
+ Django-1.8.14.tar.gz
+ Django-1.8.15-py2.py3-none-any.whl
+ Django-1.8.15.tar.gz
+ Django-1.8.16-py2.py3-none-any.whl
+ Django-1.8.16.tar.gz
+ Django-1.8.17-py2.py3-none-any.whl
+ Django-1.8.17.tar.gz
+ Django-1.8.18-py2.py3-none-any.whl
+ Django-1.8.18.tar.gz
+ Django-1.8.19-py2.py3-none-any.whl
+ Django-1.8.19.tar.gz
+ Django-1.9a1-py2.py3-none-any.whl
+ Django-1.9b1-py2.py3-none-any.whl
+ Django-1.9rc1.tar.gz
+ Django-1.9rc2-py2.py3-none-any.whl
+ Django-1.9-py2.py3-none-any.whl
+ Django-1.9.tar.gz
+ Django-1.9.1-py2.py3-none-any.whl
+ Django-1.9.1.tar.gz
+ Django-1.9.2-py2.py3-none-any.whl
+ Django-1.9.2.tar.gz
+ Django-1.9.3-py2.py3-none-any.whl
+ Django-1.9.3.tar.gz
+ Django-1.9.4-py2.py3-none-any.whl
+ Django-1.9.4.tar.gz
+ Django-1.9.5-py2.py3-none-any.whl
+ Django-1.9.5.tar.gz
+ Django-1.9.6-py2.py3-none-any.whl
+ Django-1.9.6.tar.gz
+ Django-1.9.7-py2.py3-none-any.whl
+ Django-1.9.7.tar.gz
+ Django-1.9.8-py2.py3-none-any.whl
+ Django-1.9.8.tar.gz
+ Django-1.9.9-py2.py3-none-any.whl
+ Django-1.9.9.tar.gz
+ Django-1.9.10-py2.py3-none-any.whl
+ Django-1.9.10.tar.gz
+ Django-1.9.11-py2.py3-none-any.whl
+ Django-1.9.11.tar.gz
+ Django-1.9.12-py2.py3-none-any.whl
+ Django-1.9.12.tar.gz
+ Django-1.9.13-py2.py3-none-any.whl
+ Django-1.9.13.tar.gz
+ Django-1.10a1-py2.py3-none-any.whl
+ Django-1.10a1.tar.gz
+ Django-1.10b1-py2.py3-none-any.whl
+ Django-1.10b1.tar.gz
+ Django-1.10rc1-py2.py3-none-any.whl
+ Django-1.10rc1.tar.gz
+ Django-1.10-py2.py3-none-any.whl
+ Django-1.10.tar.gz
+ Django-1.10.1-py2.py3-none-any.whl
+ Django-1.10.1.tar.gz
+ Django-1.10.2-py2.py3-none-any.whl
+ Django-1.10.2.tar.gz
+ Django-1.10.3-py2.py3-none-any.whl
+ Django-1.10.3.tar.gz
+ Django-1.10.4-py2.py3-none-any.whl
+ Django-1.10.4.tar.gz
+ Django-1.10.5-py2.py3-none-any.whl
+ Django-1.10.5.tar.gz
+ Django-1.10.6-py2.py3-none-any.whl
+ Django-1.10.6.tar.gz
+ Django-1.10.7-py2.py3-none-any.whl
+ Django-1.10.7.tar.gz
+ Django-1.10.8-py2.py3-none-any.whl
+ Django-1.10.8.tar.gz
+ Django-1.11a1-py2.py3-none-any.whl
+ Django-1.11b1-py2.py3-none-any.whl
+ Django-1.11rc1-py2.py3-none-any.whl
+ Django-1.11rc1.tar.gz
+ Django-1.11-py2.py3-none-any.whl
+ Django-1.11.tar.gz
+ Django-1.11.1-py2.py3-none-any.whl
+ Django-1.11.1.tar.gz
+ Django-1.11.2-py2.py3-none-any.whl
+ Django-1.11.2.tar.gz
+ Django-1.11.3-py2.py3-none-any.whl
+ Django-1.11.3.tar.gz
+ Django-1.11.4-py2.py3-none-any.whl
+ Django-1.11.4.tar.gz
+ Django-1.11.5-py2.py3-none-any.whl
+ Django-1.11.5.tar.gz
+ Django-1.11.6-py2.py3-none-any.whl
+ Django-1.11.6.tar.gz
+ Django-1.11.7-py2.py3-none-any.whl
+ Django-1.11.7.tar.gz
+ Django-1.11.8-py2.py3-none-any.whl
+ Django-1.11.8.tar.gz
+ Django-1.11.9-py2.py3-none-any.whl
+ Django-1.11.9.tar.gz
+ Django-1.11.10-py2.py3-none-any.whl
+ Django-1.11.10.tar.gz
+ Django-1.11.11-py2.py3-none-any.whl
+ Django-1.11.11.tar.gz
+ Django-1.11.12-py2.py3-none-any.whl
+ Django-1.11.12.tar.gz
+ Django-1.11.13-py2.py3-none-any.whl
+ Django-1.11.13.tar.gz
+ Django-1.11.14-py2.py3-none-any.whl
+ Django-1.11.14.tar.gz
+ Django-1.11.15-py2.py3-none-any.whl
+ Django-1.11.15.tar.gz
+ Django-1.11.16-py2.py3-none-any.whl
+ Django-1.11.16.tar.gz
+ Django-1.11.17-py2.py3-none-any.whl
+ Django-1.11.17.tar.gz
+ Django-1.11.18-py2.py3-none-any.whl
+ Django-1.11.18.tar.gz
+ Django-1.11.20-py2.py3-none-any.whl
+ Django-1.11.20.tar.gz
+ Django-1.11.21-py2.py3-none-any.whl
+ Django-1.11.21.tar.gz
+ Django-1.11.22-py2.py3-none-any.whl
+ Django-1.11.22.tar.gz
+ Django-1.11.23-py2.py3-none-any.whl
+ Django-1.11.23.tar.gz
+ Django-1.11.24-py2.py3-none-any.whl
+ Django-1.11.24.tar.gz
+ Django-1.11.25-py2.py3-none-any.whl
+ Django-1.11.25.tar.gz
+ Django-1.11.26-py2.py3-none-any.whl
+ Django-1.11.26.tar.gz
+ Django-1.11.27-py2.py3-none-any.whl
+ Django-1.11.27.tar.gz
+ Django-1.11.28-py2.py3-none-any.whl
+ Django-1.11.28.tar.gz
+ Django-1.11.29-py2.py3-none-any.whl
+ Django-1.11.29.tar.gz
+ Django-2.0a1-py3-none-any.whl
+ Django-2.0b1-py3-none-any.whl
+ Django-2.0rc1-py3-none-any.whl
+ Django-2.0-py3-none-any.whl
+ Django-2.0.tar.gz
+ Django-2.0.1-py3-none-any.whl
+ Django-2.0.1.tar.gz
+ Django-2.0.2-py3-none-any.whl
+ Django-2.0.2.tar.gz
+ Django-2.0.3-py3-none-any.whl
+ Django-2.0.3.tar.gz
+ Django-2.0.4-py3-none-any.whl
+ Django-2.0.4.tar.gz
+ Django-2.0.5-py3-none-any.whl
+ Django-2.0.5.tar.gz
+ Django-2.0.6-py3-none-any.whl
+ Django-2.0.6.tar.gz
+ Django-2.0.7-py3-none-any.whl
+ Django-2.0.7.tar.gz
+ Django-2.0.8-py3-none-any.whl
+ Django-2.0.8.tar.gz
+ Django-2.0.9-py3-none-any.whl
+ Django-2.0.9.tar.gz
+ Django-2.0.10-py3-none-any.whl
+ Django-2.0.10.tar.gz
+ Django-2.0.12-py3-none-any.whl
+ Django-2.0.12.tar.gz
+ Django-2.0.13-py3-none-any.whl
+ Django-2.0.13.tar.gz
+ Django-2.1a1-py3-none-any.whl
+ Django-2.1b1-py3-none-any.whl
+ Django-2.1rc1-py3-none-any.whl
+ Django-2.1-py3-none-any.whl
+ Django-2.1.tar.gz
+ Django-2.1.1-py3-none-any.whl
+ Django-2.1.1.tar.gz
+ Django-2.1.2-py3-none-any.whl
+ Django-2.1.2.tar.gz
+ Django-2.1.3-py3-none-any.whl
+ Django-2.1.3.tar.gz
+ Django-2.1.4-py3-none-any.whl
+ Django-2.1.4.tar.gz
+ Django-2.1.5-py3-none-any.whl
+ Django-2.1.5.tar.gz
+ Django-2.1.7-py3-none-any.whl
+ Django-2.1.7.tar.gz
+ Django-2.1.8-py3-none-any.whl
+ Django-2.1.8.tar.gz
+ Django-2.1.9-py3-none-any.whl
+ Django-2.1.9.tar.gz
+ Django-2.1.10-py3-none-any.whl
+ Django-2.1.10.tar.gz
+ Django-2.1.11-py3-none-any.whl
+ Django-2.1.11.tar.gz
+ Django-2.1.12-py3-none-any.whl
+ Django-2.1.12.tar.gz
+ Django-2.1.13-py3-none-any.whl
+ Django-2.1.13.tar.gz
+ Django-2.1.14-py3-none-any.whl
+ Django-2.1.14.tar.gz
+ Django-2.1.15-py3-none-any.whl
+ Django-2.1.15.tar.gz
+ Django-2.2a1-py3-none-any.whl
+ Django-2.2a1.tar.gz
+ Django-2.2b1-py3-none-any.whl
+ Django-2.2b1.tar.gz
+ Django-2.2rc1-py3-none-any.whl
+ Django-2.2rc1.tar.gz
+ Django-2.2-py3-none-any.whl
+ Django-2.2.tar.gz
+ Django-2.2.1-py3-none-any.whl
+ Django-2.2.1.tar.gz
+ Django-2.2.2-py3-none-any.whl
+ Django-2.2.2.tar.gz
+ Django-2.2.3-py3-none-any.whl
+ Django-2.2.3.tar.gz
+ Django-2.2.4-py3-none-any.whl
+ Django-2.2.4.tar.gz
+ Django-2.2.5-py3-none-any.whl
+ Django-2.2.5.tar.gz
+ Django-2.2.6-py3-none-any.whl
+ Django-2.2.6.tar.gz
+ Django-2.2.7-py3-none-any.whl
+ Django-2.2.7.tar.gz
+ Django-2.2.8-py3-none-any.whl
+ Django-2.2.8.tar.gz
+ Django-2.2.9-py3-none-any.whl
+ Django-2.2.9.tar.gz
+ Django-2.2.10-py3-none-any.whl
+ Django-2.2.10.tar.gz
+ Django-2.2.11-py3-none-any.whl
+ Django-2.2.11.tar.gz
+ Django-2.2.12-py3-none-any.whl
+ Django-2.2.12.tar.gz
+ Django-2.2.13-py3-none-any.whl
+ Django-2.2.13.tar.gz
+ Django-2.2.14-py3-none-any.whl
+ Django-2.2.14.tar.gz
+ Django-2.2.15-py3-none-any.whl
+ Django-2.2.15.tar.gz
+ Django-2.2.16-py3-none-any.whl
+ Django-2.2.16.tar.gz
+ Django-2.2.17-py3-none-any.whl
+ Django-2.2.17.tar.gz
+ Django-2.2.18-py3-none-any.whl
+ Django-2.2.18.tar.gz
+ Django-2.2.19-py3-none-any.whl
+ Django-2.2.19.tar.gz
+ Django-2.2.20-py3-none-any.whl
+ Django-2.2.20.tar.gz
+ Django-2.2.21-py3-none-any.whl
+ Django-2.2.21.tar.gz
+ Django-2.2.22-py3-none-any.whl
+ Django-2.2.22.tar.gz
+ Django-2.2.23-py3-none-any.whl
+ Django-2.2.23.tar.gz
+ Django-2.2.24-py3-none-any.whl
+ Django-2.2.24.tar.gz
+ Django-3.0a1-py3-none-any.whl
+ Django-3.0a1.tar.gz
+ Django-3.0b1-py3-none-any.whl
+ Django-3.0b1.tar.gz
+ Django-3.0rc1-py3-none-any.whl
+ Django-3.0rc1.tar.gz
+ Django-3.0-py3-none-any.whl
+ Django-3.0.tar.gz
+ Django-3.0.1-py3-none-any.whl
+ Django-3.0.1.tar.gz
+ Django-3.0.2-py3-none-any.whl
+ Django-3.0.2.tar.gz
+ Django-3.0.3-py3-none-any.whl
+ Django-3.0.3.tar.gz
+ Django-3.0.4-py3-none-any.whl
+ Django-3.0.4.tar.gz
+ Django-3.0.5-py3-none-any.whl
+ Django-3.0.5.tar.gz
+ Django-3.0.6-py3-none-any.whl
+ Django-3.0.6.tar.gz
+ Django-3.0.7-py3-none-any.whl
+ Django-3.0.7.tar.gz
+ Django-3.0.8-py3-none-any.whl
+ Django-3.0.8.tar.gz
+ Django-3.0.9-py3-none-any.whl
+ Django-3.0.9.tar.gz
+ Django-3.0.10-py3-none-any.whl
+ Django-3.0.10.tar.gz
+ Django-3.0.11-py3-none-any.whl
+ Django-3.0.11.tar.gz
+ Django-3.0.12-py3-none-any.whl
+ Django-3.0.12.tar.gz
+ Django-3.0.13-py3-none-any.whl
+ Django-3.0.13.tar.gz
+ Django-3.0.14-py3-none-any.whl
+ Django-3.0.14.tar.gz
+ Django-3.1a1-py3-none-any.whl
+ Django-3.1a1.tar.gz
+ Django-3.1b1-py3-none-any.whl
+ Django-3.1b1.tar.gz
+ Django-3.1rc1-py3-none-any.whl
+ Django-3.1rc1.tar.gz
+ Django-3.1-py3-none-any.whl
+ Django-3.1.tar.gz
+ Django-3.1.1-py3-none-any.whl
+ Django-3.1.1.tar.gz
+ Django-3.1.2-py3-none-any.whl
+ Django-3.1.2.tar.gz
+ Django-3.1.3-py3-none-any.whl
+ Django-3.1.3.tar.gz
+ Django-3.1.4-py3-none-any.whl
+ Django-3.1.4.tar.gz
+ Django-3.1.5-py3-none-any.whl
+ Django-3.1.5.tar.gz
+ Django-3.1.6-py3-none-any.whl
+ Django-3.1.6.tar.gz
+ Django-3.1.7-py3-none-any.whl
+ Django-3.1.7.tar.gz
+ Django-3.1.8-py3-none-any.whl
+ Django-3.1.8.tar.gz
+ Django-3.1.9-py3-none-any.whl
+ Django-3.1.9.tar.gz
+ Django-3.1.10-py3-none-any.whl
+ Django-3.1.10.tar.gz
+ Django-3.1.11-py3-none-any.whl
+ Django-3.1.11.tar.gz
+ Django-3.1.12-py3-none-any.whl
+ Django-3.1.12.tar.gz
+ Django-3.2a1-py3-none-any.whl
+ Django-3.2a1.tar.gz
+ Django-3.2b1-py3-none-any.whl
+ Django-3.2b1.tar.gz
+ Django-3.2rc1-py3-none-any.whl
+ Django-3.2rc1.tar.gz
+ Django-3.2-py3-none-any.whl
+ Django-3.2.tar.gz
+ Django-3.2.1-py3-none-any.whl
+ Django-3.2.1.tar.gz
+ Django-3.2.2-py3-none-any.whl
+ Django-3.2.2.tar.gz
+ Django-3.2.3-py3-none-any.whl
+ Django-3.2.3.tar.gz
+ Django-3.2.4-py3-none-any.whl
+ Django-3.2.4.tar.gz
+
+
+
diff --git a/uv/spec/fixtures/pypi/pypi_simple_response_extra.html b/uv/spec/fixtures/pypi/pypi_simple_response_extra.html
new file mode 100644
index 00000000000..d374bec4849
--- /dev/null
+++ b/uv/spec/fixtures/pypi/pypi_simple_response_extra.html
@@ -0,0 +1,10 @@
+
+
+
+ Links for luigi
+
+
+ Links for luigi
+ luigi-3.0.0+weasyl.2.tar.gz
+
+
diff --git a/uv/spec/fixtures/pypi/pypi_simple_response_multiline.html b/uv/spec/fixtures/pypi/pypi_simple_response_multiline.html
new file mode 100644
index 00000000000..ea3b3d27ed3
--- /dev/null
+++ b/uv/spec/fixtures/pypi/pypi_simple_response_multiline.html
@@ -0,0 +1,177 @@
+
+
+
+ Links for luigi
+
+
+ Links for luigi
+
+ luigi-1.0.9.tar.gz
+
+
+
+ luigi-1.0.10.tar.gz
+
+
+
+ luigi-1.0.18.tar.gz
+
+
+
+ luigi-2.3.0.tar.gz
+
+
+
+ luigi-1.0.20.tar.gz
+
+
+
+ luigi-1.0.7.tar.gz
+
+
+
+ luigi-1.0.23.tar.gz
+
+
+
+ luigi-1.0.14.tar.gz
+
+
+
+ luigi-2.1.0.tar.gz
+
+
+
+ luigi-1.0.24.tar.gz
+
+
+
+ luigi-1.1.2.tar.gz
+
+
+
+ luigi-1.2.1.tar.gz
+
+
+
+ luigi-2.1.1.tar.gz
+
+
+
+ luigi-2.7.0b1.tar.gz
+
+
+
+ luigi-2.3.1.tar.gz
+
+
+
+ luigi-1.0.4.tar.gz
+
+
+
+ luigi-1.1.1.tar.gz
+
+
+
+ luigi-1.0.12.tar.gz
+
+
+
+ luigi-2.4.0.tar.gz
+
+
+
+ luigi-1.3.0.tar.gz
+
+
+
+ luigi-2.3.3.tar.gz
+
+
+
+ luigi-1.1.0.tar.gz
+
+
+
+ luigi-1.0.5.tar.gz
+
+
+
+ luigi-1.0.2.tar.gz
+
+
+
+ luigi-2.5.0.tar.gz
+
+
+
+ luigi-2.6.0.tar.gz
+
+
+
+ luigi-1.0.1.tar.gz
+
+
+
+ luigi-2.2.0.tar.gz
+
+
+
+ luigi-1.0.9.macosx-10.7-intel.tar.gz
+
+
+
+ luigi-1.0.22.tar.gz
+
+
+
+ luigi-1.0.17.tar.gz
+
+
+
+ luigi-1.0.13.tar.gz
+
+
+
+ luigi-1.0.11.tar.gz
+
+
+
+ luigi-1.0.16.tar.gz
+
+
+
+ luigi-2.0.1.tar.gz
+
+
+
+ luigi-2.3.2.tar.gz
+
+
+
+ luigi-1.0.3.tar.gz
+
+
+
+ luigi-1.0.6.tar.gz
+
+
+
+ luigi-1.0.15.tar.gz
+
+
+
+ luigi-1.0.19.tar.gz
+
+
+
+ luigi-2.0.0.tar.gz
+
+
+
+ luigi-1.0.tar.gz
+
+
+
+
diff --git a/uv/spec/fixtures/pypi/pypi_simple_response_requests.html b/uv/spec/fixtures/pypi/pypi_simple_response_requests.html
new file mode 100644
index 00000000000..3184d7484a1
--- /dev/null
+++ b/uv/spec/fixtures/pypi/pypi_simple_response_requests.html
@@ -0,0 +1,195 @@
+
+
+
+ Links for requests
+
+
+ Links for requests
+ requests-0.2.0.tar.gz
+ requests-0.2.1.tar.gz
+ requests-0.2.2.tar.gz
+ requests-0.2.3.tar.gz
+ requests-0.2.4.tar.gz
+ requests-0.3.0.tar.gz
+ requests-0.3.1.tar.gz
+ requests-0.3.2.tar.gz
+ requests-0.3.3.tar.gz
+ requests-0.3.4.tar.gz
+ requests-0.4.0.tar.gz
+ requests-0.4.1.tar.gz
+ requests-0.5.0.tar.gz
+ requests-0.5.1.tar.gz
+ requests-0.6.0.tar.gz
+ requests-0.6.1.tar.gz
+ requests-0.6.2.tar.gz
+ requests-0.6.3.tar.gz
+ requests-0.6.4.tar.gz
+ requests-0.6.5.tar.gz
+ requests-0.6.6.tar.gz
+ requests-0.7.0.tar.gz
+ requests-0.7.1.tar.gz
+ requests-0.7.2.tar.gz
+ requests-0.7.3.tar.gz
+ requests-0.7.4.tar.gz
+ requests-0.7.5.tar.gz
+ requests-0.7.6.tar.gz
+ requests-0.8.0.tar.gz
+ requests-0.8.1.tar.gz
+ requests-0.8.2.tar.gz
+ requests-0.8.3.tar.gz
+ requests-0.8.4.tar.gz
+ requests-0.8.5.tar.gz
+ requests-0.8.6.tar.gz
+ requests-0.8.7.tar.gz
+ requests-0.8.8.tar.gz
+ requests-0.8.9.tar.gz
+ requests-0.9.0.tar.gz
+ requests-0.9.1.tar.gz
+ requests-0.9.2.tar.gz
+ requests-0.9.3.tar.gz
+ requests-0.10.0.tar.gz
+ requests-0.10.1.tar.gz
+ requests-0.10.2.tar.gz
+ requests-0.10.3.tar.gz
+ requests-0.10.4.tar.gz
+ requests-0.10.6.tar.gz
+ requests-0.10.7.tar.gz
+ requests-0.10.8.tar.gz
+ requests-0.11.1.tar.gz
+ requests-0.11.2.tar.gz
+ requests-0.12.0.tar.gz
+ requests-0.12.1.tar.gz
+ requests-0.13.0.tar.gz
+ requests-0.13.1.tar.gz
+ requests-0.13.2.tar.gz
+ requests-0.13.3.tar.gz
+ requests-0.13.4.tar.gz
+ requests-0.13.5.tar.gz
+ requests-0.13.6.tar.gz
+ requests-0.13.7.tar.gz
+ requests-0.13.8.tar.gz
+ requests-0.13.9.tar.gz
+ requests-0.14.0.tar.gz
+ requests-0.14.1.tar.gz
+ requests-0.14.2.tar.gz
+ requests-1.0.0.tar.gz
+ requests-1.0.1.tar.gz
+ requests-1.0.2.tar.gz
+ requests-1.0.3.tar.gz
+ requests-1.0.4.tar.gz
+ requests-1.1.0.tar.gz
+ requests-1.2.0.tar.gz
+ requests-1.2.1.tar.gz
+ requests-1.2.2.tar.gz
+ requests-1.2.3.tar.gz
+ requests-2.0.0-py2.py3-none-any.whl
+ requests-2.0.0.tar.gz
+ requests-2.0.1-py2.py3-none-any.whl
+ requests-2.0.1.tar.gz
+ requests-2.1.0-py2.py3-none-any.whl
+ requests-2.1.0.tar.gz
+ requests-2.2.0-py2.py3-none-any.whl
+ requests-2.2.0.tar.gz
+ requests-2.2.1-py2.py3-none-any.whl
+ requests-2.2.1.tar.gz
+ requests-2.3.0-py2.py3-none-any.whl
+ requests-2.3.0.tar.gz
+ requests-2.4.0-py2.py3-none-any.whl
+ requests-2.4.0.tar.gz
+ requests-2.4.1-py2.py3-none-any.whl
+ requests-2.4.1.tar.gz
+ requests-2.4.2-py2.py3-none-any.whl
+ requests-2.4.2.tar.gz
+ requests-2.4.3-py2.py3-none-any.whl
+ requests-2.4.3.tar.gz
+ requests-2.5.0-py2.py3-none-any.whl
+ requests-2.5.0.tar.gz
+ requests-2.5.1-py2.py3-none-any.whl
+ requests-2.5.1.tar.gz
+ requests-2.5.2-py2.py3-none-any.whl
+ requests-2.5.2.tar.gz
+ requests-2.5.3-py2.py3-none-any.whl
+ requests-2.5.3.tar.gz
+ requests-2.6.0-py2.py3-none-any.whl
+ requests-2.6.0.tar.gz
+ requests-2.6.1-py2.py3-none-any.whl
+ requests-2.6.1.tar.gz
+ requests-2.6.2-py2.py3-none-any.whl
+ requests-2.6.2.tar.gz
+ requests-2.7.0-py2.py3-none-any.whl
+ requests-2.7.0.tar.gz
+ requests-2.8.0-py2.py3-none-any.whl
+ requests-2.8.0.tar.gz
+ requests-2.8.1-py2.py3-none-any.whl
+ requests-2.8.1.tar.gz
+ requests-2.9.0-py2.py3-none-any.whl
+ requests-2.9.0.tar.gz
+ requests-2.9.1-py2.py3-none-any.whl
+ requests-2.9.1.tar.gz
+ requests-2.9.2-py2.py3-none-any.whl
+ requests-2.9.2.tar.gz
+ requests-2.10.0-py2.py3-none-any.whl
+ requests-2.10.0.tar.gz
+ requests-2.11.0-py2.py3-none-any.whl
+ requests-2.11.0.tar.gz
+ requests-2.11.1-py2.py3-none-any.whl
+ requests-2.11.1.tar.gz
+ requests-2.12.0-py2.py3-none-any.whl
+ requests-2.12.0.tar.gz
+ requests-2.12.1-py2.py3-none-any.whl
+ requests-2.12.1.tar.gz
+ requests-2.12.2-py2.py3-none-any.whl
+ requests-2.12.2.tar.gz
+ requests-2.12.3-py2.py3-none-any.whl
+ requests-2.12.3.tar.gz
+ requests-2.12.4-py2.py3-none-any.whl
+ requests-2.12.4.tar.gz
+ requests-2.12.5-py2.py3-none-any.whl
+ requests-2.12.5.tar.gz
+ requests-2.13.0-py2.py3-none-any.whl
+ requests-2.13.0.tar.gz
+ requests-2.14.0-py2.py3-none-any.whl
+ requests-2.14.0.tar.gz
+ requests-2.14.1-py2.py3-none-any.whl
+ requests-2.14.1.tar.gz
+ requests-2.14.2-py2.py3-none-any.whl
+ requests-2.14.2.tar.gz
+ requests-2.15.1-py2.py3-none-any.whl
+ requests-2.15.1.tar.gz
+ requests-2.16.0-py2.py3-none-any.whl
+ requests-2.16.0.tar.gz
+ requests-2.16.1-py2.py3-none-any.whl
+ requests-2.16.1.tar.gz
+ requests-2.16.2-py2.py3-none-any.whl
+ requests-2.16.2.tar.gz
+ requests-2.16.3-py2.py3-none-any.whl
+ requests-2.16.3.tar.gz
+ requests-2.16.4-py2.py3-none-any.whl
+ requests-2.16.4.tar.gz
+ requests-2.16.5-py2.py3-none-any.whl
+ requests-2.16.5.tar.gz
+ requests-2.17.0-py2.py3-none-any.whl
+ requests-2.17.0.tar.gz
+ requests-2.17.1-py2.py3-none-any.whl
+ requests-2.17.1.tar.gz
+ requests-2.17.2-py2.py3-none-any.whl
+ requests-2.17.2.tar.gz
+ requests-2.17.3-py2.py3-none-any.whl
+ requests-2.17.3.tar.gz
+ requests-2.18.0-py2.py3-none-any.whl
+ requests-2.18.0.tar.gz
+ requests-2.18.1-py2.py3-none-any.whl
+ requests-2.18.1.tar.gz
+ requests-2.18.2-py2.py3-none-any.whl
+ requests-2.18.2.tar.gz
+ requests-2.18.3-py2.py3-none-any.whl
+ requests-2.18.3.tar.gz
+ requests-2.18.4-py2.py3-none-any.whl
+ requests-2.18.4.tar.gz
+ requests-2.19.0-py2.py3-none-any.whl
+ requests-2.19.0.tar.gz
+ requests-2.19.1-py2.py3-none-any.whl
+ requests-2.19.1.tar.gz
+
+
+
\ No newline at end of file
diff --git a/uv/spec/fixtures/pypi/pypi_simple_response_space.html b/uv/spec/fixtures/pypi/pypi_simple_response_space.html
new file mode 100644
index 00000000000..2ccdb8a608d
--- /dev/null
+++ b/uv/spec/fixtures/pypi/pypi_simple_response_space.html
@@ -0,0 +1,93 @@
+
+
+
+ Links for luigi
+
+
+ Links for luigi
+ Luigi_ext-1.0.9.tar.gz
+
+ Luigi_ext-1.0.10.tar.gz
+
+ Luigi_ext-1.0.18.tar.gz
+
+ Luigi_ext-2.3.0.tar.gz
+
+ Luigi_ext-1.0.20.tar.gz
+
+ Luigi_ext-1.0.7.tar.gz
+
+ Luigi_ext-1.0.23.tar.gz
+
+ Luigi_ext-1.0.14.tar.gz
+
+ Luigi_ext-2.1.0.tar.gz
+
+ Luigi_ext-1.0.24.tar.gz
+
+ Luigi_ext-1.1.2.tar.gz
+
+ Luigi_ext-1.2.1.tar.gz
+
+ Luigi_ext-2.1.1.tar.gz
+
+ Luigi_ext-2.7.0b1.tar.gz
+
+ Luigi_ext-2.3.1.tar.gz
+
+ Luigi_ext-1.0.4.tar.gz
+
+ Luigi_ext-1.1.1.tar.gz
+
+ Luigi_ext-1.0.12.tar.gz
+
+ Luigi_ext-2.4.0.tar.gz
+
+ Luigi_ext-1.3.0.tar.gz
+
+ Luigi_ext-2.3.3.tar.gz
+
+ Luigi_ext-1.1.0.tar.gz
+
+ Luigi_ext-1.0.5.tar.gz
+
+ Luigi_ext-1.0.2.tar.gz
+
+ Luigi_ext-2.5.0.tar.gz
+
+ Luigi Ext-2.6.0-py2.py3.tar.gz
+
+ Luigi_ext-1.0.1.tar.gz
+
+ Luigi_ext-2.2.0.tar.gz
+
+ Luigi_ext-1.0.9.macosx-10.7-intel.tar.gz
+
+ Luigi_ext-1.0.22.tar.gz
+
+ Luigi_ext-1.0.17.tar.gz
+
+ Luigi_ext-1.0.13.tar.gz
+
+ Luigi_ext-1.0.11.tar.gz
+
+ Luigi_ext-1.0.16.tar.gz
+
+ Luigi_ext-2.0.1.tar.gz
+
+ Luigi_ext-2.3.2.tar.gz
+
+ Luigi_ext-1.0.3.tar.gz
+
+ Luigi_ext-1.0.6.tar.gz
+
+ Luigi_ext-1.0.15.tar.gz
+
+ Luigi_ext-1.0.19.tar.gz
+
+ Luigi_ext-2.0.0.tar.gz
+
+ Luigi_ext-1.0.tar.gz
+
+
+
diff --git a/uv/spec/fixtures/pypi/pypi_simple_response_underscore.html b/uv/spec/fixtures/pypi/pypi_simple_response_underscore.html
new file mode 100644
index 00000000000..ebab49629b4
--- /dev/null
+++ b/uv/spec/fixtures/pypi/pypi_simple_response_underscore.html
@@ -0,0 +1,93 @@
+
+
+
+ Links for luigi
+
+
+ Links for luigi
+ Luigi_ext-1.0.9.tar.gz
+
+ Luigi_ext-1.0.10.tar.gz
+
+ Luigi_ext-1.0.18.tar.gz
+
+ Luigi_ext-2.3.0.tar.gz
+
+ Luigi_ext-1.0.20.tar.gz
+
+ Luigi_ext-1.0.7.tar.gz
+
+ Luigi_ext-1.0.23.tar.gz
+
+ Luigi_ext-1.0.14.tar.gz
+
+ Luigi_ext-2.1.0.tar.gz
+
+ Luigi_ext-1.0.24.tar.gz
+
+ Luigi_ext-1.1.2.tar.gz
+
+ Luigi_ext-1.2.1.tar.gz
+
+ Luigi_ext-2.1.1.tar.gz
+
+ Luigi_ext-2.7.0b1.tar.gz
+
+ Luigi_ext-2.3.1.tar.gz
+
+ Luigi_ext-1.0.4.tar.gz
+
+ Luigi_ext-1.1.1.tar.gz
+
+ Luigi_ext-1.0.12.tar.gz
+
+ Luigi_ext-2.4.0.tar.gz
+
+ Luigi_ext-1.3.0.tar.gz
+
+ Luigi_ext-2.3.3.tar.gz
+
+ Luigi_ext-1.1.0.tar.gz
+
+ Luigi_ext-1.0.5.tar.gz
+
+ Luigi_ext-1.0.2.tar.gz
+
+ Luigi_ext-2.5.0.tar.gz
+
+ Luigi_ext-2.6.0.tar.gz
+
+ Luigi_ext-1.0.1.tar.gz
+
+ Luigi_ext-2.2.0.tar.gz
+
+ Luigi_ext-1.0.9.macosx-10.7-intel.tar.gz
+
+ Luigi_ext-1.0.22.tar.gz
+
+ Luigi_ext-1.0.17.tar.gz
+
+ Luigi_ext-1.0.13.tar.gz
+
+ Luigi_ext-1.0.11.tar.gz
+
+ Luigi_ext-1.0.16.tar.gz
+
+ Luigi_ext-2.0.1.tar.gz
+
+ Luigi_ext-2.3.2.tar.gz
+
+ Luigi_ext-1.0.3.tar.gz
+
+ Luigi_ext-1.0.6.tar.gz
+
+ Luigi_ext-1.0.15.tar.gz
+
+ Luigi_ext-1.0.19.tar.gz
+
+ Luigi_ext-2.0.0.tar.gz
+
+ Luigi_ext-1.0.tar.gz
+
+
+
diff --git a/uv/spec/fixtures/pypi/pypi_simple_response_urllib3.html b/uv/spec/fixtures/pypi/pypi_simple_response_urllib3.html
new file mode 100644
index 00000000000..3f4ad055c79
--- /dev/null
+++ b/uv/spec/fixtures/pypi/pypi_simple_response_urllib3.html
@@ -0,0 +1,82 @@
+
+
+
+ Links for urllib3
+
+
+ Links for urllib3
+ urllib3-0.3.tar.gz
+ urllib3-1.0.tar.gz
+ urllib3-1.0.1.tar.gz
+ urllib3-1.0.2.tar.gz
+ urllib3-1.1.tar.gz
+ urllib3-1.2.tar.gz
+ urllib3-1.2.1.tar.gz
+ urllib3-1.2.2.tar.gz
+ urllib3-1.3.tar.gz
+ urllib3-1.4.tar.gz
+ urllib3-1.5.tar.gz
+ urllib3-1.6.tar.gz
+ urllib3-1.7.tar.gz
+ urllib3-1.7.1.tar.gz
+ urllib3-1.8.tar.gz
+ urllib3-1.8.2.tar.gz
+ urllib3-1.8.3.tar.gz
+ urllib3-1.9.tar.gz
+ urllib3-1.9.1-py2-none-any.whl
+ urllib3-1.9.1.tar.gz
+ urllib3-1.10-py2-none-any.whl
+ urllib3-1.10.tar.gz
+ urllib3-1.10.1-py2-none-any.whl
+ urllib3-1.10.1.tar.gz
+ urllib3-1.10.2-py2-none-any.whl
+ urllib3-1.10.2.tar.gz
+ urllib3-1.10.3-py2-none-any.whl
+ urllib3-1.10.3.tar.gz
+ urllib3-1.10.4-py2-none-any.whl
+ urllib3-1.10.4.tar.gz
+ urllib3-1.11-py2.py3-none-any.whl
+ urllib3-1.11.tar.gz
+ urllib3-1.12-py2.py3-none-any.whl
+ urllib3-1.12.tar.gz
+ urllib3-1.13-py2.py3-none-any.whl
+ urllib3-1.13.tar.gz
+ urllib3-1.13.1-py2.py3-none-any.whl
+ urllib3-1.13.1.tar.gz
+ urllib3-1.14-py2.py3-none-any.whl
+ urllib3-1.14.tar.gz
+ urllib3-1.15-py2.py3-none-any.whl
+ urllib3-1.15.tar.gz
+ urllib3-1.15.1-py2.py3-none-any.whl
+ urllib3-1.15.1.tar.gz
+ urllib3-1.16-py2.py3-none-any.whl
+ urllib3-1.16.tar.gz
+ urllib3-1.17-py2.py3-none-any.whl
+ urllib3-1.17.tar.gz
+ urllib3-1.18-py2.py3-none-any.whl
+ urllib3-1.18.tar.gz
+ urllib3-1.18.1-py2.py3-none-any.whl
+ urllib3-1.18.1.tar.gz
+ urllib3-1.19-py2.py3-none-any.whl
+ urllib3-1.19.tar.gz
+ urllib3-1.19.1-py2.py3-none-any.whl
+ urllib3-1.19.1.tar.gz
+ urllib3-1.20-py2.py3-none-any.whl
+ urllib3-1.20.tar.gz
+ urllib3-1.21-py2.py3-none-any.whl
+ urllib3-1.21.tar.gz
+ urllib3-1.21.1-py2.py3-none-any.whl
+ urllib3-1.21.1.tar.gz
+ urllib3-1.22-py2.py3-none-any.whl
+ urllib3-1.22.tar.gz
+ urllib3-1.23-py2.py3-none-any.whl
+ urllib3-1.23.tar.gz
+ urllib3-1.24-py2.py3-none-any.whl
+ urllib3-1.24.tar.gz
+ urllib3-1.24.1-py2.py3-none-any.whl
+ urllib3-1.24.1.tar.gz
+ urllib3-1.24.2-py2.py3-none-any.whl
+ urllib3-1.24.2.tar.gz
+
+
+
\ No newline at end of file
diff --git a/uv/spec/fixtures/pypi/pypi_simple_response_yanked.html b/uv/spec/fixtures/pypi/pypi_simple_response_yanked.html
new file mode 100644
index 00000000000..fd1fe4db3b2
--- /dev/null
+++ b/uv/spec/fixtures/pypi/pypi_simple_response_yanked.html
@@ -0,0 +1,93 @@
+
+
+
+ Links for luigi
+
+
+ Links for luigi
+ luigi-1.0.9.tar.gz
+
+ luigi-1.0.10.tar.gz
+
+ luigi-1.0.18.tar.gz
+
+ luigi-2.3.0.tar.gz
+
+ luigi-1.0.20.tar.gz
+
+ luigi-1.0.7.tar.gz
+
+ luigi-1.0.23.tar.gz
+
+ luigi-1.0.14.tar.gz
+
+ luigi-2.1.0.tar.gz
+
+ luigi-1.0.24.tar.gz
+
+ luigi-1.1.2.tar.gz
+
+ luigi-1.2.1.tar.gz
+
+ luigi-2.1.1.tar.gz
+
+ luigi-2.7.0b1.tar.gz
+
+ luigi-2.3.1.tar.gz
+
+ luigi-1.0.4.tar.gz
+
+ luigi-1.1.1.tar.gz
+
+ luigi-1.0.12.tar.gz
+
+ luigi-2.4.0.tar.gz
+
+ luigi-1.3.0.tar.gz
+
+ luigi-2.3.3.tar.gz
+
+ luigi-1.1.0.tar.gz
+
+ luigi-1.0.5.tar.gz
+
+ luigi-1.0.2.tar.gz
+
+ luigi-2.5.0.tar.gz
+
+ luigi-2.6.0.tar.gz
+
+ luigi-1.0.1.tar.gz
+
+ luigi-2.2.0.tar.gz
+
+ luigi-1.0.9.macosx-10.7-intel.tar.gz
+
+ luigi-1.0.22.tar.gz
+
+ luigi-1.0.17.tar.gz
+
+ luigi-1.0.13.tar.gz
+
+ luigi-1.0.11.tar.gz
+
+ luigi-1.0.16.tar.gz
+
+ luigi-2.0.1.tar.gz
+
+ luigi-2.3.2.tar.gz
+
+ luigi-1.0.3.tar.gz
+
+ luigi-1.0.6.tar.gz
+
+ luigi-1.0.15.tar.gz
+
+ luigi-1.0.19.tar.gz
+
+ luigi-2.0.0.tar.gz
+
+ luigi-1.0.tar.gz
+
+
+
diff --git a/uv/spec/fixtures/pypi/pypi_simple_response_zip.html b/uv/spec/fixtures/pypi/pypi_simple_response_zip.html
new file mode 100644
index 00000000000..b1aed6c982f
--- /dev/null
+++ b/uv/spec/fixtures/pypi/pypi_simple_response_zip.html
@@ -0,0 +1,93 @@
+
+
+
+ Links for luigi
+
+
+ Links for luigi
+ luigi-1.0.9.zip
+
+ luigi-1.0.10.zip
+
+ luigi-1.0.18.zip
+
+ luigi-2.3.0.zip
+
+ luigi-1.0.20.zip
+
+ luigi-1.0.7.zip
+
+ luigi-1.0.23.zip
+
+ luigi-1.0.14.zip
+
+ luigi-2.1.0.zip
+
+ luigi-1.0.24.zip
+
+ luigi-1.1.2.zip
+
+ luigi-1.2.1.zip
+
+ luigi-2.1.1.zip
+
+ luigi-2.7.0b1.zip
+
+ luigi-2.3.1.zip
+
+ luigi-1.0.4.zip
+
+ luigi-1.1.1.zip
+
+ luigi-1.0.12.zip
+
+ luigi-2.4.0.zip
+
+ luigi-1.3.0.zip
+
+ luigi-2.3.3.zip
+
+ luigi-1.1.0.zip
+
+ luigi-1.0.5.zip
+
+ luigi-1.0.2.zip
+
+ luigi-2.5.0.zip
+
+ luigi-2.6.0.zip
+
+ luigi-1.0.1.zip
+
+ luigi-2.2.0.zip
+
+ luigi-1.0.9.macosx-10.7-intel.zip
+
+ luigi-1.0.22.zip
+
+ luigi-1.0.17.zip
+
+ luigi-1.0.13.zip
+
+ luigi-1.0.11.zip
+
+ luigi-1.0.16.zip
+
+ luigi-2.0.1.zip
+
+ luigi-2.3.2.zip
+
+ luigi-1.0.3.zip
+
+ luigi-1.0.6.zip
+
+ luigi-1.0.15.zip
+
+ luigi-1.0.19.zip
+
+ luigi-2.0.0.zip
+
+ luigi-1.0.zip
+
+
+
diff --git a/uv/spec/fixtures/pyproject_files/basic_poetry_dependencies.toml b/uv/spec/fixtures/pyproject_files/basic_poetry_dependencies.toml
new file mode 100644
index 00000000000..5c1b6248cfe
--- /dev/null
+++ b/uv/spec/fixtures/pyproject_files/basic_poetry_dependencies.toml
@@ -0,0 +1,28 @@
+[tool.poetry]
+name = "PythonProjects"
+version = "2.0.0"
+homepage = "https://github.com/roghu/py3_projects"
+license = "MIT"
+readme = "README.md"
+authors = ["Dependabot "]
+description = "Various small python projects."
+
+[tool.poetry.dependencies]
+python = "^3.6 || ^3.7"
+geopy = "^1.13"
+Pillow = "^5.1"
+requests = "^2.18"
+
+[tool.poetry.dev-dependencies]
+black = "^18.5"
+flake8 = "^3.5"
+flake8-comprehensions = "^1.4"
+httmock = "^1.2"
+hypothesis = "^3.56"
+mypy = "^0.600"
+pytest = "^3.5"
+pytest-cov = "^2.5"
+pytest-mock = "^1.9"
+pytest-sugar = "^0.9"
+pytest-random-order = "^0.7"
+tox = "^3.0"
diff --git a/uv/spec/fixtures/pyproject_files/black_configuration.toml b/uv/spec/fixtures/pyproject_files/black_configuration.toml
new file mode 100644
index 00000000000..97df71def5e
--- /dev/null
+++ b/uv/spec/fixtures/pyproject_files/black_configuration.toml
@@ -0,0 +1,2 @@
+[tool.black]
+skip_string_normalization = true
diff --git a/uv/spec/fixtures/pyproject_files/caret_version.toml b/uv/spec/fixtures/pyproject_files/caret_version.toml
new file mode 100644
index 00000000000..df5f8770a91
--- /dev/null
+++ b/uv/spec/fixtures/pyproject_files/caret_version.toml
@@ -0,0 +1,12 @@
+[tool.poetry]
+name = "pendulum"
+version = "2.0.0"
+homepage = "https://github.com/roghu/py3_projects"
+license = "MIT"
+readme = "README.md"
+authors = ["Dependabot "]
+description = "Python datetimes made easy"
+
+[tool.poetry.dependencies]
+python = "^3.7"
+requests = "^1.0.0"
diff --git a/uv/spec/fixtures/pyproject_files/conflict_at_latest.toml b/uv/spec/fixtures/pyproject_files/conflict_at_latest.toml
new file mode 100644
index 00000000000..2b31cca21b0
--- /dev/null
+++ b/uv/spec/fixtures/pyproject_files/conflict_at_latest.toml
@@ -0,0 +1,16 @@
+[tool.poetry]
+name = "PythonProjects"
+version = "2.0.0"
+homepage = "https://github.com/roghu/py3_projects"
+license = "MIT"
+readme = "README.md"
+authors = ["Dependabot "]
+description = "Various small python projects."
+
+[tool.poetry.dependencies]
+python = "^3.7"
+requests = "2.6.0"
+chardet = "3.0.0"
+
+[tool.poetry.dev-dependencies]
+pytest = "3.4.0"
diff --git a/uv/spec/fixtures/pyproject_files/different_requirements.toml b/uv/spec/fixtures/pyproject_files/different_requirements.toml
new file mode 100644
index 00000000000..7ea0a8c9a99
--- /dev/null
+++ b/uv/spec/fixtures/pyproject_files/different_requirements.toml
@@ -0,0 +1,28 @@
+[tool.poetry]
+name = "streamlit-server-state"
+version = "0.17.1"
+description = ""
+authors = ["Yuichiro Tachibana (Tsuchiya) "]
+license = "MIT"
+readme = "README.md"
+repository = "https://github.com/whitphx/streamlit-server-state"
+
+[tool.poetry.dependencies]
+streamlit = ">=0.65.0"
+packaging = ">=20.0"
+
+[tool.poetry.group.dev.dependencies]
+black = "^20.8b1"
+isort = "^5.12.0"
+flake8 = "^4.0.1"
+mypy = "^1.6"
+pytest = "^7.4.2"
+streamlit = "^1.12.2"
+
+[tool.isort]
+profile = "black"
+multi_line_output = 3
+
+[build-system]
+requires = ["poetry-core>=1.0.0"]
+build-backend = "poetry.core.masonry.api"
diff --git a/uv/spec/fixtures/pyproject_files/different_requirements_legacy.toml b/uv/spec/fixtures/pyproject_files/different_requirements_legacy.toml
new file mode 100644
index 00000000000..4a3ccd94387
--- /dev/null
+++ b/uv/spec/fixtures/pyproject_files/different_requirements_legacy.toml
@@ -0,0 +1,28 @@
+[tool.poetry]
+name = "streamlit-server-state"
+version = "0.17.1"
+description = ""
+authors = ["Yuichiro Tachibana (Tsuchiya) "]
+license = "MIT"
+readme = "README.md"
+repository = "https://github.com/whitphx/streamlit-server-state"
+
+[tool.poetry.dependencies]
+streamlit = ">=0.65.0"
+packaging = ">=20.0"
+
+[tool.poetry.dev-dependencies]
+black = "^20.8b1"
+isort = "^5.12.0"
+flake8 = "^4.0.1"
+mypy = "^1.6"
+pytest = "^7.4.2"
+streamlit = "^1.12.2"
+
+[tool.isort]
+profile = "black"
+multi_line_output = 3
+
+[build-system]
+requires = ["poetry-core>=1.0.0"]
+build-backend = "poetry.core.masonry.api"
diff --git a/uv/spec/fixtures/pyproject_files/different_requirements_main.toml b/uv/spec/fixtures/pyproject_files/different_requirements_main.toml
new file mode 100644
index 00000000000..8fd112925c2
--- /dev/null
+++ b/uv/spec/fixtures/pyproject_files/different_requirements_main.toml
@@ -0,0 +1,28 @@
+[tool.poetry]
+name = "streamlit-server-state"
+version = "0.17.1"
+description = ""
+authors = ["Yuichiro Tachibana (Tsuchiya) "]
+license = "MIT"
+readme = "README.md"
+repository = "https://github.com/whitphx/streamlit-server-state"
+
+[tool.poetry.dependencies]
+packaging = ">=20.0"
+streamlit = "^1.12.2"
+
+[tool.poetry.dev-dependencies]
+black = "^20.8b1"
+isort = "^5.12.0"
+flake8 = "^4.0.1"
+mypy = "^1.6"
+pytest = "^7.4.2"
+streamlit = ">=0.65.0"
+
+[tool.isort]
+profile = "black"
+multi_line_output = 3
+
+[build-system]
+requires = ["poetry-core>=1.0.0"]
+build-backend = "poetry.core.masonry.api"
diff --git a/uv/spec/fixtures/pyproject_files/dir_dependency.toml b/uv/spec/fixtures/pyproject_files/dir_dependency.toml
new file mode 100644
index 00000000000..dc80060f4f6
--- /dev/null
+++ b/uv/spec/fixtures/pyproject_files/dir_dependency.toml
@@ -0,0 +1,14 @@
+[tool.poetry]
+name = "PythonProjects"
+version = "2.0.0"
+homepage = "https://github.com/roghu/py3_projects"
+license = "MIT"
+readme = "README.md"
+authors = ["Dependabot "]
+description = "Various small python projects."
+
+[tool.poetry.dependencies]
+python = "^3.7"
+toml = { path = "../toml" }
+pytest = "*"
+
diff --git a/uv/spec/fixtures/pyproject_files/extra_source.toml b/uv/spec/fixtures/pyproject_files/extra_source.toml
new file mode 100644
index 00000000000..1fbbeccc917
--- /dev/null
+++ b/uv/spec/fixtures/pyproject_files/extra_source.toml
@@ -0,0 +1,16 @@
+[tool.poetry]
+name = "PythonProjects"
+version = "2.0.0"
+homepage = "https://github.com/roghu/py3_projects"
+license = "MIT"
+readme = "README.md"
+authors = ["Dependabot "]
+description = "Various small python projects."
+
+[tool.poetry.dependencies]
+python = "^3.7"
+requests = "2.18.0"
+
+[[tool.poetry.source]]
+name = "custom"
+url = "https://some.internal.registry.com/pypi/"
diff --git a/uv/spec/fixtures/pyproject_files/extra_source_explicit.toml b/uv/spec/fixtures/pyproject_files/extra_source_explicit.toml
new file mode 100644
index 00000000000..26b3527ae39
--- /dev/null
+++ b/uv/spec/fixtures/pyproject_files/extra_source_explicit.toml
@@ -0,0 +1,17 @@
+[tool.poetry]
+name = "PythonProjects"
+version = "2.0.0"
+homepage = "https://github.com/roghu/py3_projects"
+license = "MIT"
+readme = "README.md"
+authors = ["Dependabot "]
+description = "Various small python projects."
+
+[tool.poetry.dependencies]
+python = "^3.7"
+requests = "2.18.0"
+
+[[tool.poetry.source]]
+name = "custom"
+url = "https://some.internal.registry.com/pypi/"
+priority = "explicit"
diff --git a/uv/spec/fixtures/pyproject_files/extra_source_explicit_and_package_specify_source.toml b/uv/spec/fixtures/pyproject_files/extra_source_explicit_and_package_specify_source.toml
new file mode 100644
index 00000000000..6a578ede209
--- /dev/null
+++ b/uv/spec/fixtures/pyproject_files/extra_source_explicit_and_package_specify_source.toml
@@ -0,0 +1,17 @@
+[tool.poetry]
+name = "PythonProjects"
+version = "2.0.0"
+homepage = "https://github.com/roghu/py3_projects"
+license = "MIT"
+readme = "README.md"
+authors = ["Dependabot "]
+description = "Various small python projects."
+
+[tool.poetry.dependencies]
+python = "^3.7"
+requests = { version = "2.18.0", source = "custom" }
+
+[[tool.poetry.source]]
+name = "custom"
+url = "https://some.internal.registry.com/pypi/"
+priority = "explicit"
diff --git a/uv/spec/fixtures/pyproject_files/extras.toml b/uv/spec/fixtures/pyproject_files/extras.toml
new file mode 100644
index 00000000000..c9c5cf1b7d0
--- /dev/null
+++ b/uv/spec/fixtures/pyproject_files/extras.toml
@@ -0,0 +1,16 @@
+[tool.poetry]
+name = "dependabot-poetry-extras"
+version = "0.1.0"
+description = "Demo dependabot error when extras are specified in pyproject.toml"
+authors = ["Alex Kerney "]
+license = "MIT"
+
+[tool.poetry.dependencies]
+python = "^3.7"
+celery = {version = "^4.3", extras = ["redis"]}
+[tool.poetry.dev-dependencies]
+ipython = "^7.5"
+
+[build-system]
+requires = ["poetry>=0.12"]
+build-backend = "poetry.masonry.api"
diff --git a/uv/spec/fixtures/pyproject_files/file_dependency.toml b/uv/spec/fixtures/pyproject_files/file_dependency.toml
new file mode 100644
index 00000000000..abb2ecb692b
--- /dev/null
+++ b/uv/spec/fixtures/pyproject_files/file_dependency.toml
@@ -0,0 +1,14 @@
+[tool.poetry]
+name = "PythonProjects"
+version = "2.0.0"
+homepage = "https://github.com/roghu/py3_projects"
+license = "MIT"
+readme = "README.md"
+authors = ["Dependabot "]
+description = "Various small python projects."
+
+[tool.poetry.dependencies]
+python = "^3.7"
+toml = { path = "toml-8.2.54.tar.gz" }
+pytest = "*"
+
diff --git a/uv/spec/fixtures/pyproject_files/git_conflict.toml b/uv/spec/fixtures/pyproject_files/git_conflict.toml
new file mode 100644
index 00000000000..2438acd500c
--- /dev/null
+++ b/uv/spec/fixtures/pyproject_files/git_conflict.toml
@@ -0,0 +1,40 @@
+[tool.poetry]
+name = "meine-stadt-transparent"
+version = "0.2.0"
+description = "A website to bring municipal politics to citizens"
+authors = ["Tobias Hößl ", "Konstantin Schütze "]
+license = "MIT"
+
+[tool.poetry.dependencies]
+Django = "^1.11"
+django-allauth = "^0.37"
+django-anymail = "^4.1"
+django-braces = "^1.13"
+django_csp = "^3.4"
+django-debug-toolbar = "^1.9"
+django-elasticsearch-dsl = "^0.4"
+django-environ = "^0.4"
+django-geojson = "^2.11"
+django-settings-export = "^1.2"
+django-simple-history = "^2.3"
+django-webpack-loader = "^0.6"
+django-widget-tweaks = "^1.4"
+elasticsearch-dsl = "^5.4"
+geoextract = {git = "https://github.com/meine-stadt-transparent/geoextract", rev = "0d184e264c8356d22580076d35f16866c8ce6ecc"}
+geopy = "^1.16"
+gunicorn = "^19.9"
+html2text = "^2018.1"
+icalendar = "^4.0"
+jsonfield = "^2.0"
+mysqlclient = "^1.3"
+PyPDF2 = "^1.26"
+python = "^3.7"
+python-slugify = "^1.2"
+requests = "^2.19"
+splinter = "^0.7"
+textract = {git = "https://github.com/meine-stadt-transparent/textract", rev = "0776b86cd01fbad5b2518f75a659a1e5b614a5bd"}
+Wand = "^0.4.4"
+
+[tool.poetry.dev-dependencies]
+# See https://github.com/SeleniumHQ/selenium/issues/5296
+selenium = "3.8.0"
diff --git a/uv/spec/fixtures/pyproject_files/git_dependency.toml b/uv/spec/fixtures/pyproject_files/git_dependency.toml
new file mode 100644
index 00000000000..cecf9a56ba4
--- /dev/null
+++ b/uv/spec/fixtures/pyproject_files/git_dependency.toml
@@ -0,0 +1,13 @@
+[tool.poetry]
+name = "PythonProjects"
+version = "2.0.0"
+homepage = "https://github.com/roghu/py3_projects"
+license = "MIT"
+readme = "README.md"
+authors = ["Dependabot "]
+description = "Various small python projects."
+
+[tool.poetry.dependencies]
+python = "^3.7"
+toml = { git = "https://github.com/uiri/toml.git", branch = "master" }
+pytest = "*"
diff --git a/uv/spec/fixtures/pyproject_files/git_dependency_bad_ref.toml b/uv/spec/fixtures/pyproject_files/git_dependency_bad_ref.toml
new file mode 100644
index 00000000000..0e92358be5f
--- /dev/null
+++ b/uv/spec/fixtures/pyproject_files/git_dependency_bad_ref.toml
@@ -0,0 +1,13 @@
+[tool.poetry]
+name = "PythonProjects"
+version = "2.0.0"
+homepage = "https://github.com/roghu/py3_projects"
+license = "MIT"
+readme = "README.md"
+authors = ["Dependabot "]
+description = "Various small python projects."
+
+[tool.poetry.dependencies]
+python = "^3.7"
+toml = { git = "https://github.com/uiri/toml.git", branch = "gone" }
+pytest = "*"
diff --git a/uv/spec/fixtures/pyproject_files/git_dependency_in_a_subdirectory.toml b/uv/spec/fixtures/pyproject_files/git_dependency_in_a_subdirectory.toml
new file mode 100644
index 00000000000..abf2674d6f6
--- /dev/null
+++ b/uv/spec/fixtures/pyproject_files/git_dependency_in_a_subdirectory.toml
@@ -0,0 +1,15 @@
+[tool.poetry]
+name = "dependabot-service"
+# probably not relevat for now; versions are taken from tags
+version = "1.37.2"
+description = ""
+authors = []
+readme = "README.md"
+# probably not relevant for now
+packages = []
+
+
+[tool.poetry.dependencies]
+python = "^3.10.12"
+# git+https://github.com/sysradium/dependabot-subdir-lib.git@v0.0.1#egg=dependabot-subdir-lib&subdirectory=python
+dependabot_subdir_lib = {git = "https://github.com/sysradium/dependabot-subdir-lib.git", rev = "v0.0.1", subdirectory = "python"}
diff --git a/uv/spec/fixtures/pyproject_files/git_dependency_unreachable.toml b/uv/spec/fixtures/pyproject_files/git_dependency_unreachable.toml
new file mode 100644
index 00000000000..8e15529b65c
--- /dev/null
+++ b/uv/spec/fixtures/pyproject_files/git_dependency_unreachable.toml
@@ -0,0 +1,13 @@
+[tool.poetry]
+name = "PythonProjects"
+version = "2.0.0"
+homepage = "https://github.com/roghu/py3_projects"
+license = "MIT"
+readme = "README.md"
+authors = ["Dependabot "]
+description = "Various small python projects."
+
+[tool.poetry.dependencies]
+python = "^3.7"
+toml = { git = "https://github.com/greysteil/unreachable.git", branch = "master" }
+pytest = "*"
diff --git a/uv/spec/fixtures/pyproject_files/incorrect_poetry_setup.toml b/uv/spec/fixtures/pyproject_files/incorrect_poetry_setup.toml
new file mode 100644
index 00000000000..fab8ba2187b
--- /dev/null
+++ b/uv/spec/fixtures/pyproject_files/incorrect_poetry_setup.toml
@@ -0,0 +1,28 @@
+[project]
+name = "PythonProjects"
+version = "2.0.0"
+homepage = "https://github.com/roghu/py3_projects"
+license = "MIT"
+readme = "README.md"
+authors = ["Dependabot "]
+description = "Various small python projects."
+
+[tool.poetry.dependencies]
+python = "^3.6 || ^3.7"
+geopy = "^1.13"
+Pillow = "^5.1"
+requests = "^2.18"
+
+[tool.poetry.dev-dependencies]
+black = "^18.5"
+flake8 = "^3.5"
+flake8-comprehensions = "^1.4"
+httmock = "^1.2"
+hypothesis = "^3.56"
+mypy = "^0.600"
+pytest = "^3.5"
+pytest-cov = "^2.5"
+pytest-mock = "^1.9"
+pytest-sugar = "^0.9"
+pytest-random-order = "^0.7"
+tox = "^3.0"
diff --git a/uv/spec/fixtures/pyproject_files/indented.toml b/uv/spec/fixtures/pyproject_files/indented.toml
new file mode 100644
index 00000000000..40e215d8660
--- /dev/null
+++ b/uv/spec/fixtures/pyproject_files/indented.toml
@@ -0,0 +1,12 @@
+[tool.poetry]
+name = "pendulum"
+version = "2.0.0"
+homepage = "https://github.com/roghu/py3_projects"
+license = "MIT"
+readme = "README.md"
+authors = ["Dependabot "]
+description = "Python datetimes made easy"
+
+ [tool.poetry.dependencies]
+ python = "^3.7"
+ requests = "^1.0.0"
diff --git a/uv/spec/fixtures/pyproject_files/inline_comments.toml b/uv/spec/fixtures/pyproject_files/inline_comments.toml
new file mode 100644
index 00000000000..201da230a0e
--- /dev/null
+++ b/uv/spec/fixtures/pyproject_files/inline_comments.toml
@@ -0,0 +1,26 @@
+[tool.poetry]
+name = "dependabot-poetry-bug"
+version = "0.1.0"
+description = ""
+authors = []
+
+[tool.poetry.dependencies] # Main (runtime) dependencies
+python = "~3.10"
+jsonschema = "^4.18.5" # jsonschema library
+packaging = ">=20.0"
+
+[tool.poetry.group.dev.dependencies] # Development (local) dependencies
+black = "^20.8b1"
+flake8 = "^4.0.1" # flake8
+flake8-implicit-str-concat = "^0.4.0"
+isort = "^5.9.3"
+mypy = "^1.6"
+
+[tool.poetry.group.test.dependencies]# Test dependencies
+coverage = {extras = ["toml"], version = "^7.3.2"}
+pytest = "^7.4.0"#pytest
+pytest-mock = ">=3.8.2"
+
+[build-system]
+requires = ["poetry-core"]
+build-backend = "poetry.core.masonry.api"
diff --git a/uv/spec/fixtures/pyproject_files/invalid_wildcard.toml b/uv/spec/fixtures/pyproject_files/invalid_wildcard.toml
new file mode 100644
index 00000000000..dabfa445296
--- /dev/null
+++ b/uv/spec/fixtures/pyproject_files/invalid_wildcard.toml
@@ -0,0 +1,12 @@
+[tool.poetry]
+name = "PythonProjects"
+version = "2.0.0"
+homepage = "https://github.com/roghu/py3_projects"
+license = "MIT"
+readme = "README.md"
+authors = ["Dependabot "]
+description = "Various small python projects."
+
+[tool.poetry.dependencies]
+python = "^3.7"
+requests = "2.18.^"
diff --git a/uv/spec/fixtures/pyproject_files/latest_subdep_blocked.toml b/uv/spec/fixtures/pyproject_files/latest_subdep_blocked.toml
new file mode 100644
index 00000000000..1093214ce81
--- /dev/null
+++ b/uv/spec/fixtures/pyproject_files/latest_subdep_blocked.toml
@@ -0,0 +1,12 @@
+[tool.poetry]
+name = "PythonProjects"
+version = "2.0.0"
+homepage = "https://github.com/roghu/py3_projects"
+license = "MIT"
+readme = "README.md"
+authors = ["Dependabot "]
+description = "Various small python projects."
+
+[tool.poetry.dependencies]
+python = "^3.7"
+requests = "2.18.4"
diff --git a/uv/spec/fixtures/pyproject_files/multiple_constraint_dependency.toml b/uv/spec/fixtures/pyproject_files/multiple_constraint_dependency.toml
new file mode 100644
index 00000000000..2508404de7d
--- /dev/null
+++ b/uv/spec/fixtures/pyproject_files/multiple_constraint_dependency.toml
@@ -0,0 +1,16 @@
+[tool.poetry]
+name = "PythonProjects"
+version = "2.0.0"
+homepage = "https://github.com/roghu/py3_projects"
+license = "MIT"
+readme = "README.md"
+authors = ["Dependabot "]
+description = "Various small python projects."
+
+[tool.poetry.dependencies]
+python = "^3.7"
+numpy = [
+ { version = ">=1.15,<1.22", python = ">=3.7,<3.8" },
+ { version = ">=1.22", python = ">=3.8,<3.11" }
+]
+pytest = "*"
diff --git a/uv/spec/fixtures/pyproject_files/needs_sanitization.toml b/uv/spec/fixtures/pyproject_files/needs_sanitization.toml
new file mode 100644
index 00000000000..759380b726a
--- /dev/null
+++ b/uv/spec/fixtures/pyproject_files/needs_sanitization.toml
@@ -0,0 +1,12 @@
+[tool.poetry]
+name = "{{ PythonProjects }}"
+version = "2.0.0"
+homepage = "https://github.com/roghu/py3_projects"
+license = "MIT"
+readme = "README.md"
+authors = ["Dependabot "]
+description = "Various #{small} python projects."
+
+[tool.poetry.dependencies]
+python = "^3.7"
+requests = "2.18.0"
diff --git a/uv/spec/fixtures/pyproject_files/no_dependencies.toml b/uv/spec/fixtures/pyproject_files/no_dependencies.toml
new file mode 100644
index 00000000000..c6d60e1a4a2
--- /dev/null
+++ b/uv/spec/fixtures/pyproject_files/no_dependencies.toml
@@ -0,0 +1,10 @@
+[build-system]
+requires = ["flit_core >=3.2,<4"]
+build-backend = "flit_core.buildapi"
+
+[project]
+name = "pkgtest"
+authors = [{name = "Sample", email = "sample.project@example.org"}]
+license = {file = "LICENSE"}
+classifiers = ["License :: OSI Approved :: MIT License"]
+dynamic = ["version", "description"]
diff --git a/uv/spec/fixtures/pyproject_files/no_requirements.toml b/uv/spec/fixtures/pyproject_files/no_requirements.toml
new file mode 100644
index 00000000000..48022376300
--- /dev/null
+++ b/uv/spec/fixtures/pyproject_files/no_requirements.toml
@@ -0,0 +1,31 @@
+[build-system]
+requires = ["hatchling", "hatch-fancy-pypi-readme"]
+build-backend = "hatchling.build"
+
+[project]
+name = "httpx"
+description = "The next generation HTTP client."
+license = "BSD-3-Clause"
+requires-python = ">=3.7"
+authors = [
+ { name = "Tom Christie", email = "tom@tomchristie.com" },
+]
+classifiers = [
+ "Development Status :: 4 - Beta",
+ "Environment :: Web Environment",
+ "Framework :: AsyncIO",
+ "Framework :: Trio",
+ "Intended Audience :: Developers",
+ "License :: OSI Approved :: BSD License",
+ "Operating System :: OS Independent",
+ "Programming Language :: Python :: 3",
+ "Programming Language :: Python :: 3 :: Only",
+ "Programming Language :: Python :: 3.7",
+ "Programming Language :: Python :: 3.8",
+ "Programming Language :: Python :: 3.9",
+ "Programming Language :: Python :: 3.10",
+ "Topic :: Internet :: WWW/HTTP",
+]
+dependencies = [
+ "certifi"
+]
diff --git a/uv/spec/fixtures/pyproject_files/optional_dependencies.toml b/uv/spec/fixtures/pyproject_files/optional_dependencies.toml
new file mode 100644
index 00000000000..a7c4bf33f69
--- /dev/null
+++ b/uv/spec/fixtures/pyproject_files/optional_dependencies.toml
@@ -0,0 +1,21 @@
+[build-system]
+requires = ["flit_core >=3.2,<4"]
+build-backend = "flit_core.buildapi"
+
+[project]
+name = "pkgtest"
+authors = [{name = "Sample", email = "sample.project@example.org"}]
+license = {file = "LICENSE"}
+classifiers = ["License :: OSI Approved :: MIT License"]
+dynamic = ["version", "description"]
+dependencies = [
+ "ansys-templates==0.3.0",
+]
+
+[project.optional-dependencies]
+socks = [ 'PySocks >= 1.5.6, != 1.5.7, < 2' ]
+tests = [
+ 'ddt >= 1.2.2, < 2',
+ 'pytest < 6',
+ 'mock >= 1.0.1, < 4; python_version < "3.4"',
+]
diff --git a/uv/spec/fixtures/pyproject_files/optional_dependencies_only.toml b/uv/spec/fixtures/pyproject_files/optional_dependencies_only.toml
new file mode 100644
index 00000000000..6d8c1f87a13
--- /dev/null
+++ b/uv/spec/fixtures/pyproject_files/optional_dependencies_only.toml
@@ -0,0 +1,48 @@
+[build-system]
+requires = ["maturin>=0.13,<0.14"]
+build-backend = "maturin"
+
+[project]
+name = "ffmpegwithpy"
+requires-python = ">=3.7"
+classifiers = [
+ "Programming Language :: Rust",
+ "Programming Language :: Python :: Implementation :: CPython",
+ "Programming Language :: Python :: Implementation :: PyPy",
+]
+
+[project.optional-dependencies]
+dev = [
+ "maturin==0.13.6",
+ "pytest==7.1.3",
+ "black==22.10.0",
+ "isort==5.10.1",
+ "taskipy==1.10.3",
+]
+
+[tool.maturin]
+python-source = "python"
+
+[tool.black]
+line-length = 119
+exclude = '''
+(
+ migrations
+ | .mypy_cache
+ | .pytest_cache
+ | .venv
+ | target
+)
+'''
+
+[tool.isort]
+profile = "black"
+line_length = 119
+
+[tool.taskipy.tasks]
+fmt_black = "black ."
+fmt_isort = "isort ."
+fmt_rust = "cargo fmt"
+fmt = "task fmt_black & task fmt_isort & task fmt_rust"
+
+dev = "maturin dev -E dev"
diff --git a/uv/spec/fixtures/pyproject_files/package_specify_source.toml b/uv/spec/fixtures/pyproject_files/package_specify_source.toml
new file mode 100644
index 00000000000..dbbab5083af
--- /dev/null
+++ b/uv/spec/fixtures/pyproject_files/package_specify_source.toml
@@ -0,0 +1,12 @@
+[tool.poetry]
+name = "PoetryGroups"
+version = "2.0.0"
+homepage = "https://github.com/roghu/py3_projects"
+license = "MIT"
+readme = "README.md"
+authors = ["Dependabot "]
+description = "Various small python projects."
+
+[tool.poetry.dependencies]
+python = ">=3.10"
+black = {version="^22.12.0", source="custom"}
diff --git a/uv/spec/fixtures/pyproject_files/pdm_example.toml b/uv/spec/fixtures/pyproject_files/pdm_example.toml
new file mode 100644
index 00000000000..b1846a4ed57
--- /dev/null
+++ b/uv/spec/fixtures/pyproject_files/pdm_example.toml
@@ -0,0 +1,31 @@
+[project]
+name = "demo"
+version = "0.1.0"
+description = "Fixture project from https://github.com/pdm-project/tox-pdm"
+authors = [
+ {name = "Frost Ming", email = "mianghong@gmail.com"},
+]
+dependencies = [
+ "requests~=2.25",
+]
+requires-python = ">=3.6"
+dynamic = ["classifiers"]
+license = {text = "MIT"}
+
+[project.urls]
+homepage = ""
+
+
+[project.optional-dependencies]
+lint = [
+ "flake8~=3.8",
+]
+[build-system]
+requires = ["pdm-pep517"]
+build-backend = "pdm.pep517.api"
+
+[tool]
+[tool.pdm]
+[tool.pdm.scripts]
+lint = "flake8 demo.py"
+lint-shell = {shell = "flake8 demo.py"}
diff --git a/uv/spec/fixtures/pyproject_files/pep621_exact_requirement.toml b/uv/spec/fixtures/pyproject_files/pep621_exact_requirement.toml
new file mode 100644
index 00000000000..8d380dd80e2
--- /dev/null
+++ b/uv/spec/fixtures/pyproject_files/pep621_exact_requirement.toml
@@ -0,0 +1,13 @@
+[project]
+name = "PythonProjects"
+version = "2.0.0"
+homepage = "https://github.com/roghu/py3_projects"
+license = "MIT"
+readme = "README.md"
+authors = ["Dependabot "]
+description = "Various small python projects."
+
+dependencies = [
+ "python",
+ "requests==2.18.0"
+]
diff --git a/uv/spec/fixtures/pyproject_files/poetry_exact_requirement.toml b/uv/spec/fixtures/pyproject_files/poetry_exact_requirement.toml
new file mode 100644
index 00000000000..91fa2b19dcd
--- /dev/null
+++ b/uv/spec/fixtures/pyproject_files/poetry_exact_requirement.toml
@@ -0,0 +1,12 @@
+[tool.poetry]
+name = "PythonProjects"
+version = "2.0.0"
+homepage = "https://github.com/roghu/py3_projects"
+license = "MIT"
+readme = "README.md"
+authors = ["Dependabot "]
+description = "Various small python projects."
+
+[tool.poetry.dependencies]
+python = "3.11.1"
+requests = "2.18.0"
diff --git a/uv/spec/fixtures/pyproject_files/poetry_group_dependencies.toml b/uv/spec/fixtures/pyproject_files/poetry_group_dependencies.toml
new file mode 100644
index 00000000000..a906c8fb506
--- /dev/null
+++ b/uv/spec/fixtures/pyproject_files/poetry_group_dependencies.toml
@@ -0,0 +1,20 @@
+[tool.poetry]
+name = "PoetryGroups"
+version = "2.0.0"
+homepage = "https://github.com/roghu/py3_projects"
+license = "MIT"
+readme = "README.md"
+authors = ["Dependabot "]
+description = "Various small python projects."
+
+[tool.poetry.dependencies]
+python = ">=3.10"
+
+[tool.poetry.dev-dependencies]
+black = "^22.12.0"
+
+[tool.poetry.group.dev.dependencies]
+pytest = "*"
+
+[tool.poetry.group.docs.dependencies]
+sphinx = "6.1.3"
diff --git a/uv/spec/fixtures/pyproject_files/poetry_non_package_mode.toml b/uv/spec/fixtures/pyproject_files/poetry_non_package_mode.toml
new file mode 100644
index 00000000000..92a896d56f3
--- /dev/null
+++ b/uv/spec/fixtures/pyproject_files/poetry_non_package_mode.toml
@@ -0,0 +1,22 @@
+[tool.poetry]
+package-mode = false
+
+[tool.poetry.dependencies]
+python = "^3.7"
+geopy = "^1.13"
+Pillow = "^5.1"
+requests = "^2.18"
+
+[tool.poetry.dev-dependencies]
+black = "^18.5"
+flake8 = "^3.5"
+flake8-comprehensions = "^1.4"
+httmock = "^1.2"
+hypothesis = "^3.56"
+mypy = "^0.600"
+pytest = "^3.5"
+pytest-cov = "^2.5"
+pytest-mock = "^1.9"
+pytest-sugar = "^0.9"
+pytest-random-order = "^0.7"
+tox = "^3.0"
diff --git a/uv/spec/fixtures/pyproject_files/private_secondary_source.toml b/uv/spec/fixtures/pyproject_files/private_secondary_source.toml
new file mode 100644
index 00000000000..833d31aeba3
--- /dev/null
+++ b/uv/spec/fixtures/pyproject_files/private_secondary_source.toml
@@ -0,0 +1,17 @@
+[tool.poetry]
+name = "PythonProjects"
+version = "2.0.0"
+homepage = "https://github.com/roghu/py3_projects"
+license = "MIT"
+readme = "README.md"
+authors = ["Dependabot "]
+description = "Various small python projects."
+
+[tool.poetry.dependencies]
+python = "^3.7"
+luigi = { version = "^2.8.8", source = "custom" }
+
+[[tool.poetry.source]]
+name = "custom"
+url = "https://some.internal.registry.com/pypi/"
+secondary = true
diff --git a/uv/spec/fixtures/pyproject_files/private_source.toml b/uv/spec/fixtures/pyproject_files/private_source.toml
new file mode 100644
index 00000000000..64fa8e25add
--- /dev/null
+++ b/uv/spec/fixtures/pyproject_files/private_source.toml
@@ -0,0 +1,17 @@
+[tool.poetry]
+name = "PythonProjects"
+version = "2.0.0"
+homepage = "https://github.com/roghu/py3_projects"
+license = "MIT"
+readme = "README.md"
+authors = ["Dependabot "]
+description = "Various small python projects."
+
+[tool.poetry.dependencies]
+python = "^3.7"
+requests = "2.18.0"
+
+[[tool.poetry.source]]
+name = "custom-source.1"
+url = "https://some.internal.registry.com/pypi/"
+default = true
diff --git a/uv/spec/fixtures/pyproject_files/pypi_explicit.toml b/uv/spec/fixtures/pyproject_files/pypi_explicit.toml
new file mode 100644
index 00000000000..4a90c4e5dd0
--- /dev/null
+++ b/uv/spec/fixtures/pyproject_files/pypi_explicit.toml
@@ -0,0 +1,16 @@
+[tool.poetry]
+name = "PythonProjects"
+version = "2.0.0"
+homepage = "https://github.com/roghu/py3_projects"
+license = "MIT"
+readme = "README.md"
+authors = ["Dependabot "]
+description = "Various small python projects."
+
+[tool.poetry.dependencies]
+python = "^3.7"
+requests = "2.18.0"
+
+[[tool.poetry.source]]
+name = "PyPI"
+priority = "primary"
diff --git a/uv/spec/fixtures/pyproject_files/pypi_explicit_lowercase.toml b/uv/spec/fixtures/pyproject_files/pypi_explicit_lowercase.toml
new file mode 100644
index 00000000000..bee0828a8d5
--- /dev/null
+++ b/uv/spec/fixtures/pyproject_files/pypi_explicit_lowercase.toml
@@ -0,0 +1,16 @@
+[tool.poetry]
+name = "PythonProjects"
+version = "2.0.0"
+homepage = "https://github.com/roghu/py3_projects"
+license = "MIT"
+readme = "README.md"
+authors = ["Dependabot "]
+description = "Various small python projects."
+
+[tool.poetry.dependencies]
+python = "^3.7"
+requests = "2.18.0"
+
+[[tool.poetry.source]]
+name = "pypi"
+priority = "primary"
diff --git a/uv/spec/fixtures/pyproject_files/pyproject_1_0_0.toml b/uv/spec/fixtures/pyproject_files/pyproject_1_0_0.toml
new file mode 100644
index 00000000000..998a8616ec0
--- /dev/null
+++ b/uv/spec/fixtures/pyproject_files/pyproject_1_0_0.toml
@@ -0,0 +1,22 @@
+[build-system]
+requires = ["setuptools", "setuptools-scm"]
+build-backend = "setuptools.build_meta"
+
+[project]
+name = "dependabot-pyproject-toml-error"
+description = '''foo'''
+version = "0.0.1"
+requires-python = ">=3.12"
+license = { text = "GNU General Public License v3 or later (GPLv3+)" }
+classifiers = [
+ '''Development Status :: 4 - Beta''',
+ "Programming Language :: Python :: 3 :: Only",
+]
+dependencies = [
+ '''pydantic==2.7.0''',
+]
+
+[tool.coverage.report]
+exclude_also = [
+ '''if __name__ == ['"]__main__['"]:''',
+]
diff --git a/uv/spec/fixtures/pyproject_files/pyproject_1_0_0_nodeps.toml b/uv/spec/fixtures/pyproject_files/pyproject_1_0_0_nodeps.toml
new file mode 100644
index 00000000000..ee091069eb9
--- /dev/null
+++ b/uv/spec/fixtures/pyproject_files/pyproject_1_0_0_nodeps.toml
@@ -0,0 +1,19 @@
+[build-system]
+requires = ["setuptools", "setuptools-scm"]
+build-backend = "setuptools.build_meta"
+
+[project]
+name = "dependabot-pyproject-toml-error"
+description = '''foo'''
+version = "0.0.1"
+requires-python = ">=3.12"
+license = { text = "GNU General Public License v3 or later (GPLv3+)" }
+classifiers = [
+ '''Development Status :: 4 - Beta''',
+ "Programming Language :: Python :: 3 :: Only",
+]
+
+[tool.coverage.report]
+exclude_also = [
+ '''if __name__ == ['"]__main__['"]:''',
+]
diff --git a/uv/spec/fixtures/pyproject_files/pyproject_1_0_0_optional_deps.toml b/uv/spec/fixtures/pyproject_files/pyproject_1_0_0_optional_deps.toml
new file mode 100644
index 00000000000..7bad5cb6734
--- /dev/null
+++ b/uv/spec/fixtures/pyproject_files/pyproject_1_0_0_optional_deps.toml
@@ -0,0 +1,29 @@
+[build-system]
+requires = ["setuptools", "setuptools-scm"]
+build-backend = "setuptools.build_meta"
+
+[project]
+name = "dependabot-pyproject-toml-error"
+description = '''foo'''
+version = "0.0.1"
+requires-python = ">=3.12"
+license = { text = "GNU General Public License v3 or later (GPLv3+)" }
+classifiers = [
+ '''Development Status :: 4 - Beta''',
+ "Programming Language :: Python :: 3 :: Only",
+]
+dependencies = [
+ '''pydantic==2.7.0''',
+]
+
+[tool.coverage.report]
+exclude_also = [
+ '''if __name__ == ['"]__main__['"]:''',
+]
+[project.optional-dependencies]
+socks = [ 'PySocks >= 1.5.6, != 1.5.7, < 2' ]
+tests = [
+ 'ddt >= 1.2.2, < 2',
+ 'pytest < 6',
+ 'mock >= 1.0.1, < 4; python_version < "3.4"',
+]
diff --git a/uv/spec/fixtures/pyproject_files/pytest.toml b/uv/spec/fixtures/pyproject_files/pytest.toml
new file mode 100644
index 00000000000..746f8d06bb4
--- /dev/null
+++ b/uv/spec/fixtures/pyproject_files/pytest.toml
@@ -0,0 +1,11 @@
+[tool.poetry]
+name = "PythonProjects"
+version = "2.0.0"
+homepage = "https://github.com/roghu/py3_projects"
+license = "MIT"
+readme = "README.md"
+authors = ["Dependabot "]
+description = "Various small python projects."
+
+[package.dependencies]
+pytest = "3.4.0"
diff --git a/uv/spec/fixtures/pyproject_files/python_2.toml b/uv/spec/fixtures/pyproject_files/python_2.toml
new file mode 100644
index 00000000000..d41a04228cf
--- /dev/null
+++ b/uv/spec/fixtures/pyproject_files/python_2.toml
@@ -0,0 +1,12 @@
+[tool.poetry]
+name = "PythonProjects"
+version = "2.0.0"
+homepage = "https://github.com/roghu/py3_projects"
+license = "MIT"
+readme = "README.md"
+authors = ["Dependabot "]
+description = "Various small python projects."
+
+[tool.poetry.dependencies]
+python = "~2.6 || ^2.7"
+requests = "2.18.0"
diff --git a/uv/spec/fixtures/pyproject_files/python_310.toml b/uv/spec/fixtures/pyproject_files/python_310.toml
new file mode 100644
index 00000000000..5c5acd86ce4
--- /dev/null
+++ b/uv/spec/fixtures/pyproject_files/python_310.toml
@@ -0,0 +1,12 @@
+[tool.poetry]
+name = "PythonProjects"
+version = "2.0.0"
+homepage = "https://github.com/roghu/py3_projects"
+license = "MIT"
+readme = "README.md"
+authors = ["Dependabot "]
+description = "Various small python projects."
+
+[tool.poetry.dependencies]
+python = "3.10.7"
+requests = "2.18.0"
diff --git a/uv/spec/fixtures/pyproject_files/python_39.toml b/uv/spec/fixtures/pyproject_files/python_39.toml
new file mode 100644
index 00000000000..a1703e0d6b0
--- /dev/null
+++ b/uv/spec/fixtures/pyproject_files/python_39.toml
@@ -0,0 +1,17 @@
+[tool.poetry]
+name = "devproj"
+version = "0.1.0"
+description = ""
+authors = ["Your Name "]
+
+[tool.poetry.dependencies]
+python = "3.9.21"
+requests = "^2.27.1"
+Django = "3.0"
+
+[tool.poetry.dev-dependencies]
+pytest = "^5.2"
+
+[build-system]
+requires = ["poetry-core>=1.0.0"]
+build-backend = "poetry.core.masonry.api"
diff --git a/uv/spec/fixtures/pyproject_files/python_lower_bound.toml b/uv/spec/fixtures/pyproject_files/python_lower_bound.toml
new file mode 100644
index 00000000000..e0236e6f8d8
--- /dev/null
+++ b/uv/spec/fixtures/pyproject_files/python_lower_bound.toml
@@ -0,0 +1,19 @@
+[tool.poetry]
+name = "dependabot-poetry-auto-update-bug"
+version = "0.1.0"
+description = ""
+authors = ["firelight flagboy "]
+readme = "README.md"
+packages = [{include = "dependabot_poetry_auto_update_bug"}]
+
+[tool.poetry.dependencies]
+python = ">=3.9.10,<3.10"
+
+a-dependency = {path = "a-dependency"}
+
+[tool.poetry.group.dev.dependencies]
+black = "22.6.0"
+
+[build-system]
+requires = ["poetry-core"]
+build-backend = "poetry.core.masonry.api"
diff --git a/uv/spec/fixtures/pyproject_files/python_lower_bound_nested.toml b/uv/spec/fixtures/pyproject_files/python_lower_bound_nested.toml
new file mode 100644
index 00000000000..ec1a19da12b
--- /dev/null
+++ b/uv/spec/fixtures/pyproject_files/python_lower_bound_nested.toml
@@ -0,0 +1,14 @@
+[tool.poetry]
+name = "a-dependency"
+version = "0.1.0"
+description = ""
+authors = ["Your Name "]
+packages = [{include = "src"}]
+
+[tool.poetry.dependencies]
+python = ">=3.9.10,<3.10"
+
+
+[build-system]
+requires = ["poetry-core"]
+build-backend = "poetry.core.masonry.api"
diff --git a/uv/spec/fixtures/pyproject_files/same_requirements.toml b/uv/spec/fixtures/pyproject_files/same_requirements.toml
new file mode 100644
index 00000000000..3de4b9fc8bb
--- /dev/null
+++ b/uv/spec/fixtures/pyproject_files/same_requirements.toml
@@ -0,0 +1,14 @@
+[tool.poetry]
+name = "dependabot-poetry-bug"
+version = "0.1.0"
+description = ""
+authors = []
+
+[tool.poetry.dependencies]
+python = "^3.9"
+rq = "^1.13.0"
+dramatiq = "^1.13.0"
+
+[build-system]
+requires = ["poetry-core"]
+build-backend = "poetry.core.masonry.api"
diff --git a/uv/spec/fixtures/pyproject_files/solver_problem.toml b/uv/spec/fixtures/pyproject_files/solver_problem.toml
new file mode 100644
index 00000000000..da7925279cc
--- /dev/null
+++ b/uv/spec/fixtures/pyproject_files/solver_problem.toml
@@ -0,0 +1,14 @@
+[tool.poetry]
+name = "PythonProjects"
+version = "2.0.0"
+homepage = "https://github.com/roghu/py3_projects"
+license = "MIT"
+readme = "README.md"
+authors = ["Dependabot "]
+description = "Various small python projects."
+
+[tool.poetry.dependencies]
+requests = "2.18.0"
+
+[tool.poetry.dev-dependencies]
+black = "^18"
diff --git a/uv/spec/fixtures/pyproject_files/standard_python.toml b/uv/spec/fixtures/pyproject_files/standard_python.toml
new file mode 100644
index 00000000000..d5fc77172bc
--- /dev/null
+++ b/uv/spec/fixtures/pyproject_files/standard_python.toml
@@ -0,0 +1,13 @@
+[build-system]
+requires = ["flit_core >=3.2,<4"]
+build-backend = "flit_core.buildapi"
+
+[project]
+name = "pkgtest"
+authors = [{name = "Sample", email = "sample.project@example.org"}]
+license = {file = "LICENSE"}
+classifiers = ["License :: OSI Approved :: MIT License"]
+dynamic = ["version", "description"]
+dependencies = [
+ "ansys-templates==0.3.0",
+]
diff --git a/uv/spec/fixtures/pyproject_files/standard_python_tilde_version.toml b/uv/spec/fixtures/pyproject_files/standard_python_tilde_version.toml
new file mode 100644
index 00000000000..949b1d5c713
--- /dev/null
+++ b/uv/spec/fixtures/pyproject_files/standard_python_tilde_version.toml
@@ -0,0 +1,12 @@
+[project]
+name = "pendulum"
+version = "2.0.0"
+homepage = "https://github.com/roghu/py3_projects"
+license = "MIT"
+readme = "README.md"
+authors = ["Dependabot "]
+description = "Python datetimes made easy"
+
+dependencies = [
+ "requests~=1.0.0"
+]
diff --git a/uv/spec/fixtures/pyproject_files/table.toml b/uv/spec/fixtures/pyproject_files/table.toml
new file mode 100644
index 00000000000..15675fe93a8
--- /dev/null
+++ b/uv/spec/fixtures/pyproject_files/table.toml
@@ -0,0 +1,19 @@
+[tool.poetry]
+name = "pendulum"
+version = "2.0.0"
+homepage = "https://github.com/roghu/py3_projects"
+license = "MIT"
+readme = "README.md"
+authors = ["Dependabot "]
+description = "Python datetimes made easy"
+
+[tool.isort]
+combine_star = true
+indent = " "
+length_sort = false
+line_length = 79
+multi_line_output = 3
+
+[tool.poetry.dev-dependencies.isort]
+version = "^5.4"
+extras = [ "pyproject",]
diff --git a/uv/spec/fixtures/pyproject_files/table_build_system_requires.toml b/uv/spec/fixtures/pyproject_files/table_build_system_requires.toml
new file mode 100644
index 00000000000..821f37ab8a7
--- /dev/null
+++ b/uv/spec/fixtures/pyproject_files/table_build_system_requires.toml
@@ -0,0 +1,11 @@
+[build-system]
+requires = ["requests~=1.0.0"]
+
+[project]
+name = "pendulum"
+version = "2.0.0"
+homepage = "https://github.com/roghu/py3_projects"
+license = "MIT"
+readme = "README.md"
+authors = ["Dependabot "]
+description = "Python datetimes made easy"
diff --git a/uv/spec/fixtures/pyproject_files/table_version_conflicts.toml b/uv/spec/fixtures/pyproject_files/table_version_conflicts.toml
new file mode 100644
index 00000000000..11a20c59309
--- /dev/null
+++ b/uv/spec/fixtures/pyproject_files/table_version_conflicts.toml
@@ -0,0 +1,23 @@
+[tool.poetry]
+name = "pendulum"
+version = "2.0.0"
+homepage = "https://github.com/roghu/py3_projects"
+license = "MIT"
+readme = "README.md"
+authors = ["Dependabot "]
+description = "Python datetimes made easy"
+
+[tool.isort]
+combine_star = true
+indent = " "
+length_sort = false
+line_length = 79
+multi_line_output = 3
+
+[tool.poetry.dev-dependencies.isort]
+extras = [ "pyproject",]
+version = "^5.4"
+
+[tool.poetry.dev-dependencies.pytest]
+extras = [ "pyproject",]
+version = "^5.4"
diff --git a/uv/spec/fixtures/pyproject_files/table_version_last.toml b/uv/spec/fixtures/pyproject_files/table_version_last.toml
new file mode 100644
index 00000000000..dce8314993f
--- /dev/null
+++ b/uv/spec/fixtures/pyproject_files/table_version_last.toml
@@ -0,0 +1,19 @@
+[tool.poetry]
+name = "pendulum"
+version = "2.0.0"
+homepage = "https://github.com/roghu/py3_projects"
+license = "MIT"
+readme = "README.md"
+authors = ["Dependabot "]
+description = "Python datetimes made easy"
+
+[tool.isort]
+combine_star = true
+indent = " "
+length_sort = false
+line_length = 79
+multi_line_output = 3
+
+[tool.poetry.dev-dependencies.isort]
+extras = [ "pyproject",]
+version = "^5.4"
diff --git a/uv/spec/fixtures/pyproject_files/tarball_path_dependency.toml b/uv/spec/fixtures/pyproject_files/tarball_path_dependency.toml
new file mode 100644
index 00000000000..dbb09eb2bf3
--- /dev/null
+++ b/uv/spec/fixtures/pyproject_files/tarball_path_dependency.toml
@@ -0,0 +1,11 @@
+[tool.poetry]
+name = "PythonProjects"
+version = "2.0.0"
+homepage = "https://github.com/roghu/py3_projects"
+license = "MIT"
+readme = "README.md"
+authors = ["Dependabot "]
+description = "Various small python projects."
+
+[tool.poetry.dependencies]
+taxtea = {path = "taxtea-0.6.0.tar.gz"}
diff --git a/uv/spec/fixtures/pyproject_files/tilde_version.toml b/uv/spec/fixtures/pyproject_files/tilde_version.toml
new file mode 100644
index 00000000000..446f97913ea
--- /dev/null
+++ b/uv/spec/fixtures/pyproject_files/tilde_version.toml
@@ -0,0 +1,11 @@
+[tool.poetry]
+name = "pendulum"
+version = "2.0.0"
+homepage = "https://github.com/roghu/py3_projects"
+license = "MIT"
+readme = "README.md"
+authors = ["Dependabot "]
+description = "Python datetimes made easy"
+
+[tool.poetry.dependencies]
+requests = "~1.0.0"
diff --git a/uv/spec/fixtures/pyproject_files/unparseable.toml b/uv/spec/fixtures/pyproject_files/unparseable.toml
new file mode 100644
index 00000000000..2c12fc9dc64
--- /dev/null
+++ b/uv/spec/fixtures/pyproject_files/unparseable.toml
@@ -0,0 +1,12 @@
+[tool.poetry]
+name = "PythonProjects"
+version = "2.0.0"
+homepage = "https://github.com/roghu/py3_projects"
+license = "MIT"
+readme = "README.md"
+authors = ["Dependabot "]
+description = "Various small python projects."
+
+[tool.poetry.dependencies]
+python "^3.7"
+requests = "2.18.0"
diff --git a/uv/spec/fixtures/pyproject_files/url_dependency.toml b/uv/spec/fixtures/pyproject_files/url_dependency.toml
new file mode 100644
index 00000000000..85b23d38950
--- /dev/null
+++ b/uv/spec/fixtures/pyproject_files/url_dependency.toml
@@ -0,0 +1,13 @@
+[tool.poetry]
+name = "PythonProjects"
+version = "2.0.0"
+homepage = "https://github.com/roghu/py3_projects"
+license = "MIT"
+readme = "README.md"
+authors = ["Dependabot "]
+description = "Various small python projects."
+
+[tool.poetry.dependencies]
+python = "^3.7"
+toml = { url = "https://github.com/uiri/toml/archive/refs/tags/0.10.2.tar.gz" }
+pytest = "*"
diff --git a/uv/spec/fixtures/pyproject_files/version_not_specified.toml b/uv/spec/fixtures/pyproject_files/version_not_specified.toml
new file mode 100644
index 00000000000..574c714409e
--- /dev/null
+++ b/uv/spec/fixtures/pyproject_files/version_not_specified.toml
@@ -0,0 +1,13 @@
+[tool.poetry]
+name = "PythonProjects"
+version = "2.0.0"
+homepage = "https://github.com/roghu/py3_projects"
+license = "MIT"
+readme = "README.md"
+authors = ["Dependabot "]
+description = "Various #{small} python projects."
+
+[tool.poetry.dependencies]
+python = "^3.7"
+requests = "*"
+pytest = "*"
diff --git a/uv/spec/fixtures/pyproject_files/yanked_version.toml b/uv/spec/fixtures/pyproject_files/yanked_version.toml
new file mode 100644
index 00000000000..c42b6180d4b
--- /dev/null
+++ b/uv/spec/fixtures/pyproject_files/yanked_version.toml
@@ -0,0 +1,14 @@
+[tool.poetry]
+name = "PythonProjects"
+version = "2.0.0"
+homepage = "https://github.com/roghu/py3_projects"
+license = "MIT"
+readme = "README.md"
+authors = ["Dependabot "]
+description = "Various small python projects."
+
+[tool.poetry.dependencies]
+requests = "2.18.0"
+
+[tool.poetry.dev-dependencies]
+croniter = "0.3.26"
diff --git a/uv/spec/fixtures/requirements/cascading.txt b/uv/spec/fixtures/requirements/cascading.txt
new file mode 100644
index 00000000000..f75572d958e
--- /dev/null
+++ b/uv/spec/fixtures/requirements/cascading.txt
@@ -0,0 +1,2 @@
+requests==2.4.1
+-r ./more_requirements.txt
diff --git a/uv/spec/fixtures/requirements/cascading_nested.txt b/uv/spec/fixtures/requirements/cascading_nested.txt
new file mode 100644
index 00000000000..3122ecd2c77
--- /dev/null
+++ b/uv/spec/fixtures/requirements/cascading_nested.txt
@@ -0,0 +1,2 @@
+psycopg2==2.6.1
+-r ./nested/more_requirements.txt
diff --git a/uv/spec/fixtures/requirements/comments.txt b/uv/spec/fixtures/requirements/comments.txt
new file mode 100644
index 00000000000..fd3dbc4ddff
--- /dev/null
+++ b/uv/spec/fixtures/requirements/comments.txt
@@ -0,0 +1,2 @@
+psycopg2==2.6.1 # Comment!
+luigi==2.2.0
diff --git a/uv/spec/fixtures/requirements/custom_index.txt b/uv/spec/fixtures/requirements/custom_index.txt
new file mode 100644
index 00000000000..c3915f936fe
--- /dev/null
+++ b/uv/spec/fixtures/requirements/custom_index.txt
@@ -0,0 +1,3 @@
+--index-url https://pypi.weasyldev.com/weasyl/source/+simple
+psycopg2==2.6.1
+luigi==2.2.0
diff --git a/uv/spec/fixtures/requirements/custom_index_invalid.txt b/uv/spec/fixtures/requirements/custom_index_invalid.txt
new file mode 100644
index 00000000000..b2f62a66ac8
--- /dev/null
+++ b/uv/spec/fixtures/requirements/custom_index_invalid.txt
@@ -0,0 +1,3 @@
+--index-url https://test:test^@pypi.weasyldev.com/weasyl/source/+simple
+psycopg2==2.6.1
+luigi==2.2.0
diff --git a/uv/spec/fixtures/requirements/custom_index_invalid_env.txt b/uv/spec/fixtures/requirements/custom_index_invalid_env.txt
new file mode 100644
index 00000000000..4c9fa70004b
--- /dev/null
+++ b/uv/spec/fixtures/requirements/custom_index_invalid_env.txt
@@ -0,0 +1,3 @@
+--index-url $PIP_INDEX_URL
+psycopg2==2.6.1
+luigi==2.2.0
diff --git a/uv/spec/fixtures/requirements/custom_index_quotes.txt b/uv/spec/fixtures/requirements/custom_index_quotes.txt
new file mode 100644
index 00000000000..adee0c9be5f
--- /dev/null
+++ b/uv/spec/fixtures/requirements/custom_index_quotes.txt
@@ -0,0 +1,3 @@
+--index-url "https://pypi.weasyldev.com/weasyl/source/+simple"
+psycopg2==2.6.1
+luigi==2.2.0
diff --git a/uv/spec/fixtures/requirements/custom_index_valid.txt b/uv/spec/fixtures/requirements/custom_index_valid.txt
new file mode 100644
index 00000000000..c3915f936fe
--- /dev/null
+++ b/uv/spec/fixtures/requirements/custom_index_valid.txt
@@ -0,0 +1,3 @@
+--index-url https://pypi.weasyldev.com/weasyl/source/+simple
+psycopg2==2.6.1
+luigi==2.2.0
diff --git a/uv/spec/fixtures/requirements/extra_index.txt b/uv/spec/fixtures/requirements/extra_index.txt
new file mode 100644
index 00000000000..d82713bc048
--- /dev/null
+++ b/uv/spec/fixtures/requirements/extra_index.txt
@@ -0,0 +1,3 @@
+--extra-index-url https://pypi.weasyldev.com/weasyl/source/+simple # Private index
+psycopg2==2.6.1
+luigi==2.2.0
diff --git a/uv/spec/fixtures/requirements/extra_index_quotes.txt b/uv/spec/fixtures/requirements/extra_index_quotes.txt
new file mode 100644
index 00000000000..f438d66f39c
--- /dev/null
+++ b/uv/spec/fixtures/requirements/extra_index_quotes.txt
@@ -0,0 +1,3 @@
+--extra-index-url 'https://cakebot.mycloudrepo.io/public/repositories/py' # Private index 2
+psycopg2==2.6.1
+luigi==2.2.0
diff --git a/uv/spec/fixtures/requirements/extras.txt b/uv/spec/fixtures/requirements/extras.txt
new file mode 100644
index 00000000000..84e846a1136
--- /dev/null
+++ b/uv/spec/fixtures/requirements/extras.txt
@@ -0,0 +1,2 @@
+psycopg2[foo, bar]==2.6.1
+luigi[foobar]==2.2.0
diff --git a/uv/spec/fixtures/requirements/hard_names_runtime.txt b/uv/spec/fixtures/requirements/hard_names_runtime.txt
new file mode 100644
index 00000000000..82cd6f7298a
--- /dev/null
+++ b/uv/spec/fixtures/requirements/hard_names_runtime.txt
@@ -0,0 +1,12 @@
+-i https://pypi.org/simple
+aiohttp==1.0.5
+async-timeout==3.0.0; python_version >= '3.5.3'
+certifi==2018.1.8
+chardet==3.0.4
+discord.py==0.16.1
+idna==2.5
+multidict==4.4.0; python_version >= '3.4.1'
+python-decouple==3.1
+requests==2.18.0
+urllib3==1.21.1
+websockets==3.4
diff --git a/uv/spec/fixtures/requirements/hashes.txt b/uv/spec/fixtures/requirements/hashes.txt
new file mode 100644
index 00000000000..dfaa82334ce
--- /dev/null
+++ b/uv/spec/fixtures/requirements/hashes.txt
@@ -0,0 +1 @@
+pytest==3.2.3 --hash=sha256:81a25f36a97da3313e1125fce9e7bbbba565bc7fec3c5beb14c262ddab238ac1 --hash=sha256:27fa6617efc2869d3e969a3e75ec060375bfb28831ade8b5cdd68da3a741dc3c
diff --git a/uv/spec/fixtures/requirements/hashes_512.txt b/uv/spec/fixtures/requirements/hashes_512.txt
new file mode 100644
index 00000000000..c559eb98c6b
--- /dev/null
+++ b/uv/spec/fixtures/requirements/hashes_512.txt
@@ -0,0 +1 @@
+pytest==3.2.3 --hash=sha512:7394e2426f59c39c7ddbb8d530df7fb58940c2989df34ebe47f213dfb15b1cddec67beefc341224ff1008df89f9650fe4c40810d6415d115d6714b8e1a171bc6 --hash=sha512:40abe4e290c7e91fdfae3dc33aa242df51aef0476f8a400460a6e88e5a6c3895dbe30840b221bf123f487e301b55788591abbb64a6085830ad7859e134635cc7
diff --git a/uv/spec/fixtures/requirements/hashes_multiline.txt b/uv/spec/fixtures/requirements/hashes_multiline.txt
new file mode 100644
index 00000000000..4992c99ecbc
--- /dev/null
+++ b/uv/spec/fixtures/requirements/hashes_multiline.txt
@@ -0,0 +1,3 @@
+pytest==3.2.3 \
+ --hash=sha256:81a25f36a97da3313e1125fce9e7bbbba565bc7fec3c5beb14c262ddab238ac1 \
+ --hash=sha256:27fa6617efc2869d3e969a3e75ec060375bfb28831ade8b5cdd68da3a741dc3c
diff --git a/uv/spec/fixtures/requirements/hashes_multiline_no_space.txt b/uv/spec/fixtures/requirements/hashes_multiline_no_space.txt
new file mode 100644
index 00000000000..2a699835f2a
--- /dev/null
+++ b/uv/spec/fixtures/requirements/hashes_multiline_no_space.txt
@@ -0,0 +1,3 @@
+pytest==3.2.3 \
+ --hash=sha256:81a25f36a97da3313e1125fce9e7bbbba565bc7fec3c5beb14c262ddab238ac1\
+ --hash=sha256:27fa6617efc2869d3e969a3e75ec060375bfb28831ade8b5cdd68da3a741dc3c
diff --git a/uv/spec/fixtures/requirements/hashes_single.txt b/uv/spec/fixtures/requirements/hashes_single.txt
new file mode 100644
index 00000000000..54aef6c34c7
--- /dev/null
+++ b/uv/spec/fixtures/requirements/hashes_single.txt
@@ -0,0 +1,2 @@
+flask-featureflags==0.5 \
+ --hash=sha256:dbe86c9697bf7cc76e44d6a5641726a414234fea466cb0e5df8352059333e418
diff --git a/uv/spec/fixtures/requirements/hashes_single_to_multiple.txt b/uv/spec/fixtures/requirements/hashes_single_to_multiple.txt
new file mode 100644
index 00000000000..619a103313d
--- /dev/null
+++ b/uv/spec/fixtures/requirements/hashes_single_to_multiple.txt
@@ -0,0 +1 @@
+pytest==3.2.3 --hash=sha256:81a25f36a97da3313e1125fce9e7bbbba565bc7fec3c5beb14c262ddab238ac1
diff --git a/uv/spec/fixtures/requirements/hashes_unknown_package.txt b/uv/spec/fixtures/requirements/hashes_unknown_package.txt
new file mode 100644
index 00000000000..55c73e93828
--- /dev/null
+++ b/uv/spec/fixtures/requirements/hashes_unknown_package.txt
@@ -0,0 +1,9 @@
+#
+# This file is autogenerated by pip-compile
+# To update, run:
+#
+# pip-compile --generate-hashes --output-file req.txt req.in
+#
+some_unknown_package==24.3.3 \
+ --hash=sha256:9373346h0aa638ac9154c6ffefca0de818d9bfa741eb66a99894300f734560de \
+ --hash=sha256:41b2efa462f3d37a138443bbed5ca1affa9322aaa8h35d182be9be98c03f4bc9
diff --git a/uv/spec/fixtures/requirements/incompatible_versions.txt b/uv/spec/fixtures/requirements/incompatible_versions.txt
new file mode 100644
index 00000000000..0900c79af25
--- /dev/null
+++ b/uv/spec/fixtures/requirements/incompatible_versions.txt
@@ -0,0 +1,57 @@
+#
+# This file is autogenerated by pip-compile with python 3.9
+# To update, run:
+#
+# pip-compile --resolver=legacy --output-file=requirements.txt requirements.in
+#
+ansible==2.10.4
+ # via -r requirements.in
+ansible-base==2.10.13
+ # via ansible
+awscli==1.18.198
+ # via -r requirements.in
+botocore==1.19.38
+ # via
+ # awscli
+ # s3transfer
+cffi==1.14.6
+ # via cryptography
+colorama==0.4.3
+ # via awscli
+cryptography==3.4.8
+ # via ansible-base
+docutils==0.15.2
+ # via awscli
+jinja2==3.0.1
+ # via
+ # ansible-base
+ # jinja2-cli
+jinja2-cli[yaml]==0.7.0
+ # via -r requirements.in
+jmespath==0.10.0
+ # via botocore
+markupsafe==2.0.1
+ # via jinja2
+packaging==21.0
+ # via ansible-base
+pyasn1==0.4.8
+ # via rsa
+pycparser==2.20
+ # via cffi
+pyparsing==2.4.7
+ # via packaging
+python-dateutil==2.8.2
+ # via botocore
+pyyaml==5.3.1
+ # via
+ # ansible-base
+ # awscli
+ # jinja2-cli
+rsa==4.5
+ # via awscli
+s3transfer==0.3.7
+ # via awscli
+six==1.16.0
+ # via python-dateutil
+urllib3==1.26.6
+ # via botocore
diff --git a/uv/spec/fixtures/requirements/invalid_lines.txt b/uv/spec/fixtures/requirements/invalid_lines.txt
new file mode 100644
index 00000000000..63a432f5823
--- /dev/null
+++ b/uv/spec/fixtures/requirements/invalid_lines.txt
@@ -0,0 +1,6 @@
+# This is just a comment about this file
+# with some high-level information
+
+4 + 4 = 2 # I'm not a requirement. I shouldn't be here.
+
+psycopg2==2.6.1
diff --git a/uv/spec/fixtures/requirements/invalid_options.txt b/uv/spec/fixtures/requirements/invalid_options.txt
new file mode 100644
index 00000000000..846a9e175b8
--- /dev/null
+++ b/uv/spec/fixtures/requirements/invalid_options.txt
@@ -0,0 +1,4 @@
+luigi==2.2.0
+--allow-external psycopg2
+--allow-unverified psycopg2
+psycopg2==2.6.1
diff --git a/uv/spec/fixtures/requirements/invalid_requirements.txt b/uv/spec/fixtures/requirements/invalid_requirements.txt
new file mode 100644
index 00000000000..30494a0099f
--- /dev/null
+++ b/uv/spec/fixtures/requirements/invalid_requirements.txt
@@ -0,0 +1,7 @@
+# This is a cross-platform list tracking distribution packages needed by tests;
+# see http://docs.openstack.org/infra/bindep/ for additional information.
+
+build-essential [platform:dpkg]
+gcc [platform:rpm test]
+python-hacking [platform:rpm test]
+libopenssl-devel [platform:suse !platform:rpm]
diff --git a/uv/spec/fixtures/requirements/invalid_value.txt b/uv/spec/fixtures/requirements/invalid_value.txt
new file mode 100644
index 00000000000..65015291ca0
--- /dev/null
+++ b/uv/spec/fixtures/requirements/invalid_value.txt
@@ -0,0 +1 @@
+- if it's uploaded, call it attachment on the serializers and fields
diff --git a/uv/spec/fixtures/requirements/jinja_requirements.txt b/uv/spec/fixtures/requirements/jinja_requirements.txt
new file mode 100644
index 00000000000..d6e766b931f
--- /dev/null
+++ b/uv/spec/fixtures/requirements/jinja_requirements.txt
@@ -0,0 +1,5 @@
+{%- if cookiecutter.foo == "y" %}
+psycopg2==2.6.1
+{%- endif %}
+gunicorn==20.0.2
+{{ cookiecutter.another_dependency }}
diff --git a/uv/spec/fixtures/requirements/local_version.txt b/uv/spec/fixtures/requirements/local_version.txt
new file mode 100644
index 00000000000..78ad2893850
--- /dev/null
+++ b/uv/spec/fixtures/requirements/local_version.txt
@@ -0,0 +1,2 @@
+psycopg2==2.6.1+gc.1
+luigi==2.2.0+gc.1
diff --git a/uv/spec/fixtures/requirements/malformed_markers.txt b/uv/spec/fixtures/requirements/malformed_markers.txt
new file mode 100644
index 00000000000..597ac4558d9
--- /dev/null
+++ b/uv/spec/fixtures/requirements/malformed_markers.txt
@@ -0,0 +1 @@
+arrow==1.3.0; python_version ~= 'fred'
diff --git a/uv/spec/fixtures/requirements/markers.txt b/uv/spec/fixtures/requirements/markers.txt
new file mode 100644
index 00000000000..0ed3e280cca
--- /dev/null
+++ b/uv/spec/fixtures/requirements/markers.txt
@@ -0,0 +1,2 @@
+distro==1.0.4;python_version<="2.6"
+distro==1.3.0;python_version>="2.7"
diff --git a/uv/spec/fixtures/requirements/markers_2.txt b/uv/spec/fixtures/requirements/markers_2.txt
new file mode 100644
index 00000000000..aeff59cbb40
--- /dev/null
+++ b/uv/spec/fixtures/requirements/markers_2.txt
@@ -0,0 +1,2 @@
+cryptography<2.7; platform_machine != "x86_64"
+cryptography==2.7; platform_machine == "x86_64"
diff --git a/uv/spec/fixtures/requirements/markers_and_hashes_multiline.txt b/uv/spec/fixtures/requirements/markers_and_hashes_multiline.txt
new file mode 100644
index 00000000000..3c86d85a8bc
--- /dev/null
+++ b/uv/spec/fixtures/requirements/markers_and_hashes_multiline.txt
@@ -0,0 +1,3 @@
+pytest==3.2.3 ; python_version=='2.7' \
+ --hash=sha256:81a25f36a97da3313e1125fce9e7bbbba565bc7fec3c5beb14c262ddab238ac1 \
+ --hash=sha256:27fa6617efc2869d3e969a3e75ec060375bfb28831ade8b5cdd68da3a741dc3c
diff --git a/uv/spec/fixtures/requirements/markers_with_combination_of_conditions.txt b/uv/spec/fixtures/requirements/markers_with_combination_of_conditions.txt
new file mode 100644
index 00000000000..7d4f7c4f44c
--- /dev/null
+++ b/uv/spec/fixtures/requirements/markers_with_combination_of_conditions.txt
@@ -0,0 +1,3 @@
+arrow==0.14.7; python_version < '3.0'
+arrow==1.2.3; python_version >= '3.0' and python_version <= '3.7'
+arrow==1.3.0; python_version >= '3.8'
diff --git a/uv/spec/fixtures/requirements/minor_version_specified.txt b/uv/spec/fixtures/requirements/minor_version_specified.txt
new file mode 100644
index 00000000000..0c04ff850ef
--- /dev/null
+++ b/uv/spec/fixtures/requirements/minor_version_specified.txt
@@ -0,0 +1,2 @@
+psycopg2==2.6
+luigi==2.2.0
diff --git a/uv/spec/fixtures/requirements/name_clash.txt b/uv/spec/fixtures/requirements/name_clash.txt
new file mode 100644
index 00000000000..effe5be191f
--- /dev/null
+++ b/uv/spec/fixtures/requirements/name_clash.txt
@@ -0,0 +1,2 @@
+Flask-SQLAlchemy==1.2.9
+SQLAlchemy==1.2.9
diff --git a/uv/spec/fixtures/requirements/pbr.txt b/uv/spec/fixtures/requirements/pbr.txt
new file mode 100644
index 00000000000..a5e65b67b13
--- /dev/null
+++ b/uv/spec/fixtures/requirements/pbr.txt
@@ -0,0 +1 @@
+pbr==4.0.2
diff --git a/uv/spec/fixtures/requirements/pip_compile_bounded.txt b/uv/spec/fixtures/requirements/pip_compile_bounded.txt
new file mode 100644
index 00000000000..aaba97ab084
--- /dev/null
+++ b/uv/spec/fixtures/requirements/pip_compile_bounded.txt
@@ -0,0 +1,19 @@
+#
+# This file is autogenerated by pip-compile
+# To update, run:
+#
+# pip-compile --no-annotate --output-file requirements/text.txt requirements/test.in
+#
+apipkg==1.4
+attrs==17.3.0
+execnet==1.5.0
+flaky==3.4.0
+mock==2.0.0
+more-itertools==4.1.0
+pbr==4.0.3
+pluggy==0.6.0
+py==1.5.3
+pytest-forked==0.2
+pytest-xdist==1.22.2
+pytest==3.5.1
+six==1.11.0
diff --git a/uv/spec/fixtures/requirements/pip_compile_custom_header.txt b/uv/spec/fixtures/requirements/pip_compile_custom_header.txt
new file mode 100644
index 00000000000..00553e4c790
--- /dev/null
+++ b/uv/spec/fixtures/requirements/pip_compile_custom_header.txt
@@ -0,0 +1,19 @@
+#
+# This file is autogenerated by pip-compile
+# To update, run:
+#
+# make upgrade
+#
+apipkg==1.4 # via execnet
+attrs==17.3.0
+execnet==1.5.0 # via pytest-xdist
+flaky==3.4.0
+mock==2.0.0
+more-itertools==4.1.0 # via pytest
+pbr==4.0.2 # via mock
+pluggy==0.6.0 # via pytest
+py==1.5.3 # via pytest
+pytest-forked==0.2 # via pytest-xdist
+pytest-xdist==1.22.2
+pytest==3.5.1
+six==1.11.0 # via mock, more-itertools, pytest
diff --git a/uv/spec/fixtures/requirements/pip_compile_editable.txt b/uv/spec/fixtures/requirements/pip_compile_editable.txt
new file mode 100644
index 00000000000..d19f7b8468c
--- /dev/null
+++ b/uv/spec/fixtures/requirements/pip_compile_editable.txt
@@ -0,0 +1,11 @@
+#
+# This file is autogenerated by pip-compile
+# To update, run:
+#
+# pip-compile --output-file req.txt req.in
+#
+-e git+https://github.com/testing-cabal/mock.git@2.0.0#egg=mock
+-e git+https://github.com/box/flaky.git@v3.5.3#egg=flaky
+attrs==17.3.0
+pbr==5.1.1
+six==1.12.0
diff --git a/uv/spec/fixtures/requirements/pip_compile_extra_hashes.txt b/uv/spec/fixtures/requirements/pip_compile_extra_hashes.txt
new file mode 100644
index 00000000000..1671ba2454f
--- /dev/null
+++ b/uv/spec/fixtures/requirements/pip_compile_extra_hashes.txt
@@ -0,0 +1,47 @@
+#
+# This file is autogenerated by pip-compile
+# To update, run:
+#
+# pip-compile --generate-hashes --output-file req.txt req.in
+#
+atomicwrites==1.2.1 \
+ --hash=sha256:0312ad34fcad8fac3704d441f7b317e50af620823353ec657a53e981f92920c0 \
+ --hash=sha256:ec9ae8adaae229e4f8446952d204a3e4b5fdd2d099f9be3aaf556120135fb3ee \
+ # via pytest
+attrs==18.2.0 \
+ --hash=sha256:10cbf6e27dbce8c30807caf056c8eb50917e0eaafe86347671b57254006c3e69 \
+ --hash=sha256:ca4be454458f9dec299268d472aaa5a11f67a4ff70093396e1ceae9c76cf4bbb \
+ # via pytest
+more-itertools==5.0.0 \
+ --hash=sha256:38a936c0a6d98a38bcc2d03fdaaedaba9f412879461dd2ceff8d37564d6522e4 \
+ --hash=sha256:c0a5785b1109a6bd7fac76d6837fd1feca158e54e521ccd2ae8bfe393cc9d4fc \
+ --hash=sha256:fe7a7cae1ccb57d33952113ff4fa1bc5f879963600ed74918f1236e212ee50b9 \
+ # via pytest
+pluggy==0.8.0 \
+ --hash=sha256:447ba94990e8014ee25ec853339faf7b0fc8050cdc3289d4d71f7f410fb90095 \
+ --hash=sha256:bde19360a8ec4dfd8a20dcb811780a30998101f078fc7ded6162f0076f50508f \
+ # via pytest
+py==1.7.0 \
+ --hash=sha256:bf92637198836372b520efcba9e020c330123be8ce527e535d185ed4b6f45694 \
+ --hash=sha256:e76826342cefe3c3d5f7e8ee4316b80d1dd8a300781612ddbc765c17ba25a6c6 \
+ # via pytest
+pyasn1-modules==0.1.4 \
+ --hash=sha256:2e39aead1602e4e5aa8b796260848f9383e51bea278edf7d2b4fb686944425fa \
+ --hash=sha256:34e1d014608ca4f8a0cc3164a5add93f4b8a04a3871b96d31a028ff36a6fe924 \
+ --hash=sha256:529d5d509562c22877a53771c5b394d8102c98cd62f33bb5af23b475879ea6d5 \
+ --hash=sha256:641cc18cf56d4a60679804aa8ae8cbc7359b3fa2d5559df064ecfaca27d15b10 \
+ --hash=sha256:6ad0e6772af4b74bd63c78c0102ece7b6a775f764e395137968af575c20bbfc9 \
+ --hash=sha256:7411e837c83ea4cb6088aa3bf63691d348454fcd9bb3d9cc342859282419bfcf \
+ --hash=sha256:7930d0f6109a47f78e5fb88a4f7ed2bfa1073ec9ddb2657deffa92f0805568fb \
+ --hash=sha256:a24f5118f41af33f13fa0c7e8419fc7380dfe2d2f2dc0f554d928141c842f924 \
+ --hash=sha256:ab7e23e45f32f0515e5a084eecaff22653bb6277d0d4229cb7369117abf33baa \
+ --hash=sha256:b07c17bdb34d6f64aafea6269f2e8fb306a57473f0f38d9a6ca389d6ab30ac4a \
+ --hash=sha256:beb3d344fee1fa68ddf36471c5d9120665ba049900d7fccbffa50c77036581de \
+ --hash=sha256:ca3cdc5d8ecc97f78a202009512254bd7aeef77069405e9e834b45c48a26a4db
+pytest==4.0.2 \
+ --hash=sha256:f689bf2fc18c4585403348dd56f47d87780bf217c53ed9ae7a3e2d7faa45f8e9 \
+ --hash=sha256:f812ea39a0153566be53d88f8de94839db1e8a05352ed8a49525d7d7f37861e9
+six==1.12.0 \
+ --hash=sha256:3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c \
+ --hash=sha256:d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73 \
+ # via more-itertools, pytest
diff --git a/uv/spec/fixtures/requirements/pip_compile_hashes.txt b/uv/spec/fixtures/requirements/pip_compile_hashes.txt
new file mode 100644
index 00000000000..bd183c40f3d
--- /dev/null
+++ b/uv/spec/fixtures/requirements/pip_compile_hashes.txt
@@ -0,0 +1,49 @@
+apipkg==1.4 \
+ --hash=sha256:2e38399dbe842891fe85392601aab8f40a8f4cc5a9053c326de35a1cc0297ac6 \
+ --hash=sha256:65d2aa68b28e7d31233bb2ba8eb31cda40e4671f8ac2d6b241e358c9652a74b9 \
+ # via execnet
+attrs==17.3.0 \
+ --hash=sha256:1c7960ccfd6a005cd9f7ba884e6316b5e430a3f1a6c37c5f87d8b43f83b54ec9 \
+ --hash=sha256:a17a9573a6f475c99b551c0e0a812707ddda1ec9653bed04c13841404ed6f450
+execnet==1.5.0 \
+ --hash=sha256:a7a84d5fa07a089186a329528f127c9d73b9de57f1a1131b82bb5320ee651f6a \
+ --hash=sha256:fc155a6b553c66c838d1a22dba1dc9f5f505c43285a878c6f74a79c024750b83 \
+ # via pytest-xdist
+flaky==3.4.0 \
+ --hash=sha256:4ad7880aef8c35a34ddb394d4fa33047765bca1e3d67d182bf6eba9c8eabf3a2 \
+ --hash=sha256:d0533f473a46b916e6db6e84e20b06d8a70656600a0c14e819b0760b63f70226
+mock==2.0.0 \
+ --hash=sha256:5ce3c71c5545b472da17b72268978914d0252980348636840bd34a00b5cc96c1 \
+ --hash=sha256:b158b6df76edd239b8208d481dc46b6afd45a846b7812ff0ce58971cf5bc8bba
+more-itertools==4.1.0 \
+ --hash=sha256:0dd8f72eeab0d2c3bd489025bb2f6a1b8342f9b198f6fc37b52d15cfa4531fea \
+ --hash=sha256:11a625025954c20145b37ff6309cd54e39ca94f72f6bb9576d1195db6fa2442e \
+ --hash=sha256:c9ce7eccdcb901a2c75d326ea134e0886abfbea5f93e91cc95de9507c0816c44 \
+ # via pytest
+pbr==4.0.3 \
+ --hash=sha256:680bf5ba9b28dd56e08eb7c267991a37c7a5f90a92c2e07108829931a50ff80a \
+ --hash=sha256:6874feb22334a1e9a515193cba797664e940b763440c88115009ec323a7f2df5 \
+ # via mock
+pluggy==0.6.0 \
+ --hash=sha256:7f8ae7f5bdf75671a718d2daf0a64b7885f74510bcd98b1a0bb420eb9a9d0cff \
+ --hash=sha256:d345c8fe681115900d6da8d048ba67c25df42973bda370783cd58826442dcd7c \
+ --hash=sha256:e160a7fcf25762bb60efc7e171d4497ff1d8d2d75a3d0df7a21b76821ecbf5c5 \
+ # via pytest
+py==1.5.3 \
+ --hash=sha256:29c9fab495d7528e80ba1e343b958684f4ace687327e6f789a94bf3d1915f881 \
+ --hash=sha256:983f77f3331356039fdd792e9220b7b8ee1aa6bd2b25f567a963ff1de5a64f6a \
+ # via pytest
+pytest-forked==0.2 \
+ --hash=sha256:e4500cd0509ec4a26535f7d4112a8cc0f17d3a41c29ffd4eab479d2a55b30805 \
+ --hash=sha256:f275cb48a73fc61a6710726348e1da6d68a978f0ec0c54ece5a5fae5977e5a08 \
+ # via pytest-xdist
+pytest-xdist==1.22.2 \
+ --hash=sha256:be2662264b035920ba740ed6efb1c816a83c8a22253df7766d129f6a7bfdbd35 \
+ --hash=sha256:e8f5744acc270b3e7d915bdb4d5f471670f049b6fbd163d4cbd52203b075d30f
+pytest==3.5.1 \
+ --hash=sha256:54713b26c97538db6ff0703a12b19aeaeb60b5e599de542e7fca0ec83b9038e8 \
+ --hash=sha256:829230122facf05a5f81a6d4dfe6454a04978ea3746853b2b84567ecf8e5c526
+six==1.11.0 \
+ --hash=sha256:70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9 \
+ --hash=sha256:832dc0e10feb1aa2c68dcc57dbb658f1c7e65b9b61af69048abc87a2db00a0eb \
+ # via mock, more-itertools, pytest
diff --git a/uv/spec/fixtures/requirements/pip_compile_imports_setup.txt b/uv/spec/fixtures/requirements/pip_compile_imports_setup.txt
new file mode 100644
index 00000000000..2e853c9db72
--- /dev/null
+++ b/uv/spec/fixtures/requirements/pip_compile_imports_setup.txt
@@ -0,0 +1,23 @@
+#
+# This file is autogenerated by pip-compile
+# To update, run:
+#
+# pip-compile --output-file something.txt something.in
+#
+-e file:///Users/greysteil/code/python-test
+apipkg==1.5 # via execnet
+atomicwrites==1.2.1 # via pytest
+attrs==18.2.0
+contextlib2==0.5.5 # via raven
+execnet==1.5.0 # via pytest-xdist
+flaky==3.4.0
+mock==2.0.0
+more-itertools==4.3.0 # via pytest
+pbr==4.0.2 # via mock
+pluggy==0.7.1 # via pytest
+py==1.6.0 # via pytest
+pytest-forked==0.2 # via pytest-xdist
+pytest-xdist==1.23.0
+pytest==3.7.4
+raven==5.32.0
+six==1.11.0 # via mock, more-itertools, pytest, pytest-xdist
diff --git a/uv/spec/fixtures/requirements/pip_compile_imports_shared.txt b/uv/spec/fixtures/requirements/pip_compile_imports_shared.txt
new file mode 100644
index 00000000000..2130515bc68
--- /dev/null
+++ b/uv/spec/fixtures/requirements/pip_compile_imports_shared.txt
@@ -0,0 +1,42 @@
+#
+# This file is autogenerated by pip-compile
+# To update, run:
+#
+# pip-compile --output-file req.txt req.in
+#
+asn1crypto==0.24.0 # via cryptography
+aws-xray-sdk==0.95 # via moto
+boto3==1.9.51 # via moto
+boto==2.49.0 # via moto
+botocore==1.12.51 # via boto3, moto, s3transfer
+certifi==2018.10.15 # via requests
+cffi==1.11.5 # via cryptography
+chardet==3.0.4 # via requests
+cookies==2.2.1 # via moto
+cryptography==2.4.2 # via moto
+docker-pycreds==0.3.0 # via docker
+docker==3.5.1 # via moto
+docutils==0.14 # via botocore
+idna==2.7 # via cryptography, requests
+jinja2==2.10 # via moto
+jmespath==0.9.3 # via boto3, botocore
+jsondiff==1.1.1 # via moto
+jsonpickle==1.0 # via aws-xray-sdk
+markupsafe==1.1.0 # via jinja2
+mock==2.0.0 # via moto
+moto==1.3.3
+pbr==5.1.1 # via mock
+pyaml==18.11.0 # via moto
+pycparser==2.19 # via cffi
+python-dateutil==2.6.0
+pytz==2018.7 # via moto
+pyyaml==6.0.1 # via pyaml
+requests==2.20.1 # via aws-xray-sdk, docker, moto, responses
+responses==0.10.4 # via moto
+s3transfer==0.1.13 # via boto3
+six==1.11.0 # via cryptography, docker, docker-pycreds, mock, moto, python-dateutil, responses, websocket-client
+urllib3==1.24.1 # via botocore, requests
+websocket-client==0.54.0 # via docker
+werkzeug==0.14.1 # via moto
+wrapt==1.10.11 # via aws-xray-sdk
+xmltodict==0.11.0 # via moto
diff --git a/uv/spec/fixtures/requirements/pip_compile_met_marker.txt b/uv/spec/fixtures/requirements/pip_compile_met_marker.txt
new file mode 100644
index 00000000000..3203b4acbf4
--- /dev/null
+++ b/uv/spec/fixtures/requirements/pip_compile_met_marker.txt
@@ -0,0 +1,19 @@
+#
+# This file is autogenerated by pip-compile
+# To update, run:
+#
+# pip-compile requirements.in
+#
+apipkg==1.5 # via execnet
+atomicwrites==1.3.0 # via pytest
+attrs==17.3.0
+execnet==1.6.0 # via pytest-xdist
+flaky==3.5.0 ; python_version < "2.8"
+mock==3.0.3
+more-itertools==7.0.0 # via pytest
+pluggy==0.9.0 # via pytest
+py==1.8.0 # via pytest
+pytest-forked==1.0.2 # via pytest-xdist
+pytest-xdist==1.28.0
+pytest==4.4.1
+six==1.12.0 # via mock, pytest, pytest-xdist
diff --git a/uv/spec/fixtures/requirements/pip_compile_native_dependencies.txt b/uv/spec/fixtures/requirements/pip_compile_native_dependencies.txt
new file mode 100644
index 00000000000..4b5afc0ffe6
--- /dev/null
+++ b/uv/spec/fixtures/requirements/pip_compile_native_dependencies.txt
@@ -0,0 +1,17 @@
+#
+# This file is autogenerated by pip-compile with Python 3.13
+# by the following command:
+#
+# pip-compile --annotation-style=line --output-file=pip_compile_native_dependencies.txt ../pip_compile_files/native_dependencies.in
+#
+asn1crypto==1.4.0 # via cryptography
+cffi==1.11.5 # via cryptography
+cryptography==2.2.2 # via -r ../pip_compile_files/native_dependencies.in
+idna==2.10 # via cryptography
+numpy==1.26.4 # via -r ../pip_compile_files/native_dependencies.in, pandas
+pandas==2.2.3 # via -r ../pip_compile_files/native_dependencies.in
+pycparser==2.18 # via cffi
+python-dateutil==2.9.0.post0 # via pandas
+pytz==2020.4 # via pandas
+six==1.11.0 # via cryptography, python-dateutil
+tzdata==2024.2 # via pandas
diff --git a/uv/spec/fixtures/requirements/pip_compile_no_binary.txt b/uv/spec/fixtures/requirements/pip_compile_no_binary.txt
new file mode 100644
index 00000000000..0fd6e90d694
--- /dev/null
+++ b/uv/spec/fixtures/requirements/pip_compile_no_binary.txt
@@ -0,0 +1,9 @@
+#
+# This file is autogenerated by pip-compile
+# To update, run:
+#
+# pip-compile --output-file requirements.txt requirements.in
+#
+--no-binary psycopg2
+
+psycopg2==2.7.4
diff --git a/uv/spec/fixtures/requirements/pip_compile_requests.txt b/uv/spec/fixtures/requirements/pip_compile_requests.txt
new file mode 100644
index 00000000000..c5bb465bdfa
--- /dev/null
+++ b/uv/spec/fixtures/requirements/pip_compile_requests.txt
@@ -0,0 +1,11 @@
+#
+# This file is autogenerated by pip-compile
+# To update, run:
+#
+# pip-compile --output-file requests.txt requests.in
+#
+certifi==2018.10.15 # via requests
+chardet==3.0.4 # via requests
+idna==2.6 # via requests
+requests==2.18.4
+urllib3==1.22 # via requests
diff --git a/uv/spec/fixtures/requirements/pip_compile_resolver_backtracking.txt b/uv/spec/fixtures/requirements/pip_compile_resolver_backtracking.txt
new file mode 100644
index 00000000000..7c13f208dfc
--- /dev/null
+++ b/uv/spec/fixtures/requirements/pip_compile_resolver_backtracking.txt
@@ -0,0 +1,6 @@
+# This file is autogenerated by pip-compile with Python 3.11
+# by the following command:
+#
+# pip-compile --resolver=backtracking
+#
+celery[sqs]==5.2.7
diff --git a/uv/spec/fixtures/requirements/pip_compile_resolver_legacy.txt b/uv/spec/fixtures/requirements/pip_compile_resolver_legacy.txt
new file mode 100644
index 00000000000..8977481cacd
--- /dev/null
+++ b/uv/spec/fixtures/requirements/pip_compile_resolver_legacy.txt
@@ -0,0 +1,6 @@
+# This file is autogenerated by pip-compile with Python 3.11
+# by the following command:
+#
+# pip-compile --resolver=legacy
+#
+celery[sqs]==5.2.7
diff --git a/uv/spec/fixtures/requirements/pip_compile_resolves_differently_by_python.txt b/uv/spec/fixtures/requirements/pip_compile_resolves_differently_by_python.txt
new file mode 100644
index 00000000000..4360d442402
--- /dev/null
+++ b/uv/spec/fixtures/requirements/pip_compile_resolves_differently_by_python.txt
@@ -0,0 +1,11 @@
+#
+# This file is autogenerated by pip-compile
+# To update, run:
+#
+# pip-compile --output-file requirements.txt requirements.in
+#
+backports-abc==0.5 # via tornado
+futures==3.2.0 # via tornado
+singledispatch==3.4.0.3 # via tornado
+six==1.12.0 # via singledispatch
+tornado==5.1.0
diff --git a/uv/spec/fixtures/requirements/pip_compile_safe.txt b/uv/spec/fixtures/requirements/pip_compile_safe.txt
new file mode 100644
index 00000000000..f5b21443b0c
--- /dev/null
+++ b/uv/spec/fixtures/requirements/pip_compile_safe.txt
@@ -0,0 +1,10 @@
+#
+# This file is autogenerated by pip-compile
+# To update, run:
+#
+# pip-compile --output-file dev-requirements.txt dev-requirements.in
+#
+flake8==3.5.0
+mccabe==0.6.1 # via flake8
+pycodestyle==2.4.0 # via flake8
+pyflakes==2.0.0 # via flake8
diff --git a/uv/spec/fixtures/requirements/pip_compile_setuptools.txt b/uv/spec/fixtures/requirements/pip_compile_setuptools.txt
new file mode 100644
index 00000000000..354a1e511bb
--- /dev/null
+++ b/uv/spec/fixtures/requirements/pip_compile_setuptools.txt
@@ -0,0 +1,9 @@
+#
+# This file is autogenerated by pip-compile
+# To update, run:
+#
+# pip-compile --output-file requirements.txt requirements.in
+#
+
+# The following packages are considered to be unsafe in a requirements file:
+setuptools==40.4.1
diff --git a/uv/spec/fixtures/requirements/pip_compile_strip_extras.txt b/uv/spec/fixtures/requirements/pip_compile_strip_extras.txt
new file mode 100644
index 00000000000..871e3b538b2
--- /dev/null
+++ b/uv/spec/fixtures/requirements/pip_compile_strip_extras.txt
@@ -0,0 +1,22 @@
+#
+# This file is autogenerated by pip-compile with python 3.10
+# To update, run:
+#
+# pip-compile --strip-extras --output-file=constraints.txt constraints.in
+#
+cachecontrol==0.12.10
+ # via -r constraints.in
+certifi==2021.10.8
+ # via requests
+charset-normalizer==2.0.7
+ # via requests
+idna==3.3
+ # via requests
+lockfile==0.12.2
+ # via cachecontrol
+msgpack==1.0.2
+ # via cachecontrol
+requests==2.26.0
+ # via cachecontrol
+urllib3==1.26.7
+ # via requests
diff --git a/uv/spec/fixtures/requirements/pip_compile_unmet_marker.txt b/uv/spec/fixtures/requirements/pip_compile_unmet_marker.txt
new file mode 100644
index 00000000000..eda29e363a7
--- /dev/null
+++ b/uv/spec/fixtures/requirements/pip_compile_unmet_marker.txt
@@ -0,0 +1,19 @@
+#
+# This file is autogenerated by pip-compile
+# To update, run:
+#
+# pip-compile --output-file requirements.txt requirements.in
+#
+apipkg==1.5 # via execnet
+atomicwrites==1.1.5 # via pytest
+attrs==17.3.0
+execnet==1.5.0 # via pytest-xdist
+mock==2.0.0
+more-itertools==4.3.0 # via pytest
+pbr==4.2.0 # via mock
+pluggy==0.7.1 # via pytest
+py==1.5.4 # via pytest
+pytest-forked==0.2 # via pytest-xdist
+pytest-xdist==1.22.5
+pytest==3.7.2
+six==1.11.0 # via mock, more-itertools, pytest, pytest-xdist
diff --git a/uv/spec/fixtures/requirements/pip_compile_unpinned.txt b/uv/spec/fixtures/requirements/pip_compile_unpinned.txt
new file mode 100644
index 00000000000..471c494034c
--- /dev/null
+++ b/uv/spec/fixtures/requirements/pip_compile_unpinned.txt
@@ -0,0 +1,19 @@
+#
+# This file is autogenerated by pip-compile
+# To update, run:
+#
+# pip-compile --output-file requirements/test.txt requirements/test.in
+#
+apipkg==1.4 # via execnet
+attrs==17.3.0
+execnet==1.5.0 # via pytest-xdist
+flaky==3.4.0
+mock==2.0.0
+more-itertools==4.1.0 # via pytest
+pbr==4.0.2 # via mock
+pluggy==0.6.0 # via pytest
+py==1.5.3 # via pytest
+pytest-forked==0.2 # via pytest-xdist
+pytest-xdist==1.22.2
+pytest==3.5.1
+six==1.11.0 # via mock, more-itertools, pytest
diff --git a/uv/spec/fixtures/requirements/pip_compile_unpinned_renamed.txt b/uv/spec/fixtures/requirements/pip_compile_unpinned_renamed.txt
new file mode 100644
index 00000000000..8fcb0aecd42
--- /dev/null
+++ b/uv/spec/fixtures/requirements/pip_compile_unpinned_renamed.txt
@@ -0,0 +1,19 @@
+#
+# This file is autogenerated by pip-compile
+# To update, run:
+#
+# pip-compile --output-file requirements/test-funky.txt requirements/test.in
+#
+apipkg==1.4 # via execnet
+attrs==17.3.0
+execnet==1.5.0 # via pytest-xdist
+flaky==3.4.0
+mock==2.0.0
+more-itertools==4.1.0 # via pytest
+pbr==4.0.2 # via mock
+pluggy==0.6.0 # via pytest
+py==1.5.3 # via pytest
+pytest-forked==0.2 # via pytest-xdist
+pytest-xdist==1.22.2
+pytest==3.5.1
+six==1.11.0 # via mock, more-itertools, pytest
diff --git a/uv/spec/fixtures/requirements/pip_compile_unpinned_rogue.txt b/uv/spec/fixtures/requirements/pip_compile_unpinned_rogue.txt
new file mode 100644
index 00000000000..281b30e4baf
--- /dev/null
+++ b/uv/spec/fixtures/requirements/pip_compile_unpinned_rogue.txt
@@ -0,0 +1,20 @@
+#
+# This file is autogenerated by pip-compile
+# To update, run:
+#
+# pip-compile --output-file requirements/test.txt requirements/test.in
+#
+apipkg==1.4 # via execnet
+attrs==17.3.0
+execnet==1.5.0 # via pytest-xdist
+flaky==3.4.0
+mock==2.0.0
+more-itertools==4.1.0 # via pytest
+pbr==4.0.2 # via mock
+pluggy==0.6.0 # via pytest
+py==1.5.3 # via pytest
+pytest-forked==0.2 # via pytest-xdist
+pytest-xdist==1.22.2
+pytest==3.5.1
+requests==2.18.0 # via mock
+six==1.11.0 # via mock, more-itertools, pytest
diff --git a/uv/spec/fixtures/requirements/pip_compile_unsafe.txt b/uv/spec/fixtures/requirements/pip_compile_unsafe.txt
new file mode 100644
index 00000000000..e47c6b60117
--- /dev/null
+++ b/uv/spec/fixtures/requirements/pip_compile_unsafe.txt
@@ -0,0 +1,13 @@
+#
+# This file is autogenerated by pip-compile
+# To update, run:
+#
+# pip-compile --output-file dev-requirements.txt dev-requirements.in
+#
+flake8==3.5.0
+mccabe==0.6.1 # via flake8
+pycodestyle==2.4.0 # via flake8
+pyflakes==2.0.0 # via flake8
+
+# The following packages are considered to be unsafe in a requirements file:
+setuptools==40.4.3 # via flake8
diff --git a/uv/spec/fixtures/requirements/prefix_match.txt b/uv/spec/fixtures/requirements/prefix_match.txt
new file mode 100644
index 00000000000..faef9d6c665
--- /dev/null
+++ b/uv/spec/fixtures/requirements/prefix_match.txt
@@ -0,0 +1,2 @@
+psycopg2==2.6.*
+luigi==2.2.0
diff --git a/uv/spec/fixtures/requirements/python_header.txt b/uv/spec/fixtures/requirements/python_header.txt
new file mode 100644
index 00000000000..d4903acdd94
--- /dev/null
+++ b/uv/spec/fixtures/requirements/python_header.txt
@@ -0,0 +1,6 @@
+# This file is autogenerated by pip-compile with Python 3.8
+# by the following command:
+#
+# pip-compile --resolver=backtracking
+#
+celery[sqs]==5.2.7
diff --git a/uv/spec/fixtures/requirements/python_header_lower.txt b/uv/spec/fixtures/requirements/python_header_lower.txt
new file mode 100644
index 00000000000..7258cb59dd3
--- /dev/null
+++ b/uv/spec/fixtures/requirements/python_header_lower.txt
@@ -0,0 +1,6 @@
+# This file is autogenerated by pip-compile with python 3.8
+# by the following command:
+#
+# pip-compile --resolver=backtracking
+#
+celery[sqs]==5.2.7
diff --git a/uv/spec/fixtures/requirements/remote_constraints.txt b/uv/spec/fixtures/requirements/remote_constraints.txt
new file mode 100644
index 00000000000..cc0aebdb38a
--- /dev/null
+++ b/uv/spec/fixtures/requirements/remote_constraints.txt
@@ -0,0 +1 @@
+-c "https://raw.githubusercontent.com/apache/airflow/constraints-2.7.2/constraints-3.11.txt"
diff --git a/uv/spec/fixtures/requirements/specific_with_constraints.txt b/uv/spec/fixtures/requirements/specific_with_constraints.txt
new file mode 100644
index 00000000000..3dc3ff7ff5b
--- /dev/null
+++ b/uv/spec/fixtures/requirements/specific_with_constraints.txt
@@ -0,0 +1,2 @@
+-c constraints.txt
+requests==2.4.1
diff --git a/uv/spec/fixtures/requirements/tarball_path_dependency b/uv/spec/fixtures/requirements/tarball_path_dependency
new file mode 100644
index 00000000000..00c1c7f9508
--- /dev/null
+++ b/uv/spec/fixtures/requirements/tarball_path_dependency
@@ -0,0 +1,2 @@
+packages/taxtea-0.6.0.tar.gz \
+ --hash=sha256:c07b24551537f0b9339532a7f0f4076fb2ec5a4555fa9dc449308c14c99d2988
diff --git a/uv/spec/fixtures/requirements/urllib.txt b/uv/spec/fixtures/requirements/urllib.txt
new file mode 100644
index 00000000000..a42590bebea
--- /dev/null
+++ b/uv/spec/fixtures/requirements/urllib.txt
@@ -0,0 +1 @@
+urllib3
diff --git a/uv/spec/fixtures/requirements/uv_pip_compile.txt b/uv/spec/fixtures/requirements/uv_pip_compile.txt
new file mode 100644
index 00000000000..e47dcb2a678
--- /dev/null
+++ b/uv/spec/fixtures/requirements/uv_pip_compile.txt
@@ -0,0 +1,22 @@
+# This file was autogenerated by uv via the following command:
+# uv pip compile --output-file uv_pip_compile.txt unpinned_uv.in
+attrs==18.1.0
+ # via -r unpinned_uv.in
+execnet==2.1.1
+ # via pytest-xdist
+flaky==3.8.1
+ # via -r unpinned_uv.in
+iniconfig==2.0.0
+ # via pytest
+mock==5.1.0
+ # via -r unpinned_uv.in
+packaging==24.1
+ # via pytest
+pluggy==1.5.0
+ # via pytest
+pytest==8.2.2
+ # via
+ # -r unpinned_uv.in
+ # pytest-xdist
+pytest-xdist==3.6.1
+ # via -r unpinned_uv.in
diff --git a/uv/spec/fixtures/requirements/uv_pip_compile_bounded.txt b/uv/spec/fixtures/requirements/uv_pip_compile_bounded.txt
new file mode 100644
index 00000000000..a35bb7f8e37
--- /dev/null
+++ b/uv/spec/fixtures/requirements/uv_pip_compile_bounded.txt
@@ -0,0 +1,15 @@
+# This file was autogenerated by uv via the following command:
+# uv pip compile --no-annotate --output-file requirements/text.txt requirements/test.in
+apipkg==1.4
+attrs==17.3.0
+execnet==1.5.0
+flaky==3.4.0
+mock==2.0.0
+more-itertools==4.1.0
+pbr==4.0.3
+pluggy==0.6.0
+py==1.5.3
+pytest-forked==0.2
+pytest-xdist==1.22.2
+pytest==3.5.1
+six==1.11.0
diff --git a/uv/spec/fixtures/requirements/uv_pip_compile_extra_hashes.txt b/uv/spec/fixtures/requirements/uv_pip_compile_extra_hashes.txt
new file mode 100644
index 00000000000..e0b36be5e2b
--- /dev/null
+++ b/uv/spec/fixtures/requirements/uv_pip_compile_extra_hashes.txt
@@ -0,0 +1,43 @@
+# This file was autogenerated by uv via the following command:
+# uv pip compile --generate-hashes --output-file req.txt req.in
+atomicwrites==1.2.1 \
+ --hash=sha256:0312ad34fcad8fac3704d441f7b317e50af620823353ec657a53e981f92920c0 \
+ --hash=sha256:ec9ae8adaae229e4f8446952d204a3e4b5fdd2d099f9be3aaf556120135fb3ee \
+ # via pytest
+attrs==18.2.0 \
+ --hash=sha256:10cbf6e27dbce8c30807caf056c8eb50917e0eaafe86347671b57254006c3e69 \
+ --hash=sha256:ca4be454458f9dec299268d472aaa5a11f67a4ff70093396e1ceae9c76cf4bbb \
+ # via pytest
+more-itertools==5.0.0 \
+ --hash=sha256:38a936c0a6d98a38bcc2d03fdaaedaba9f412879461dd2ceff8d37564d6522e4 \
+ --hash=sha256:c0a5785b1109a6bd7fac76d6837fd1feca158e54e521ccd2ae8bfe393cc9d4fc \
+ --hash=sha256:fe7a7cae1ccb57d33952113ff4fa1bc5f879963600ed74918f1236e212ee50b9 \
+ # via pytest
+pluggy==0.8.0 \
+ --hash=sha256:447ba94990e8014ee25ec853339faf7b0fc8050cdc3289d4d71f7f410fb90095 \
+ --hash=sha256:bde19360a8ec4dfd8a20dcb811780a30998101f078fc7ded6162f0076f50508f \
+ # via pytest
+py==1.7.0 \
+ --hash=sha256:bf92637198836372b520efcba9e020c330123be8ce527e535d185ed4b6f45694 \
+ --hash=sha256:e76826342cefe3c3d5f7e8ee4316b80d1dd8a300781612ddbc765c17ba25a6c6 \
+ # via pytest
+pyasn1-modules==0.1.4 \
+ --hash=sha256:2e39aead1602e4e5aa8b796260848f9383e51bea278edf7d2b4fb686944425fa \
+ --hash=sha256:34e1d014608ca4f8a0cc3164a5add93f4b8a04a3871b96d31a028ff36a6fe924 \
+ --hash=sha256:529d5d509562c22877a53771c5b394d8102c98cd62f33bb5af23b475879ea6d5 \
+ --hash=sha256:641cc18cf56d4a60679804aa8ae8cbc7359b3fa2d5559df064ecfaca27d15b10 \
+ --hash=sha256:6ad0e6772af4b74bd63c78c0102ece7b6a775f764e395137968af575c20bbfc9 \
+ --hash=sha256:7411e837c83ea4cb6088aa3bf63691d348454fcd9bb3d9cc342859282419bfcf \
+ --hash=sha256:7930d0f6109a47f78e5fb88a4f7ed2bfa1073ec9ddb2657deffa92f0805568fb \
+ --hash=sha256:a24f5118f41af33f13fa0c7e8419fc7380dfe2d2f2dc0f554d928141c842f924 \
+ --hash=sha256:ab7e23e45f32f0515e5a084eecaff22653bb6277d0d4229cb7369117abf33baa \
+ --hash=sha256:b07c17bdb34d6f64aafea6269f2e8fb306a57473f0f38d9a6ca389d6ab30ac4a \
+ --hash=sha256:beb3d344fee1fa68ddf36471c5d9120665ba049900d7fccbffa50c77036581de \
+ --hash=sha256:ca3cdc5d8ecc97f78a202009512254bd7aeef77069405e9e834b45c48a26a4db
+pytest==4.0.2 \
+ --hash=sha256:f689bf2fc18c4585403348dd56f47d87780bf217c53ed9ae7a3e2d7faa45f8e9 \
+ --hash=sha256:f812ea39a0153566be53d88f8de94839db1e8a05352ed8a49525d7d7f37861e9
+six==1.12.0 \
+ --hash=sha256:3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c \
+ --hash=sha256:d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73 \
+ # via more-itertools, pytest
diff --git a/uv/spec/fixtures/requirements/uv_pip_compile_hashes.txt b/uv/spec/fixtures/requirements/uv_pip_compile_hashes.txt
new file mode 100644
index 00000000000..147d25f15ab
--- /dev/null
+++ b/uv/spec/fixtures/requirements/uv_pip_compile_hashes.txt
@@ -0,0 +1,51 @@
+# This file was autogenerated by uv via the following command:
+# uv pip compile --generate-hashes --output-file req.txt req.in
+apipkg==1.4 \
+ --hash=sha256:2e38399dbe842891fe85392601aab8f40a8f4cc5a9053c326de35a1cc0297ac6 \
+ --hash=sha256:65d2aa68b28e7d31233bb2ba8eb31cda40e4671f8ac2d6b241e358c9652a74b9 \
+ # via execnet
+attrs==17.3.0 \
+ --hash=sha256:1c7960ccfd6a005cd9f7ba884e6316b5e430a3f1a6c37c5f87d8b43f83b54ec9 \
+ --hash=sha256:a17a9573a6f475c99b551c0e0a812707ddda1ec9653bed04c13841404ed6f450
+execnet==1.5.0 \
+ --hash=sha256:a7a84d5fa07a089186a329528f127c9d73b9de57f1a1131b82bb5320ee651f6a \
+ --hash=sha256:fc155a6b553c66c838d1a22dba1dc9f5f505c43285a878c6f74a79c024750b83 \
+ # via pytest-xdist
+flaky==3.4.0 \
+ --hash=sha256:4ad7880aef8c35a34ddb394d4fa33047765bca1e3d67d182bf6eba9c8eabf3a2 \
+ --hash=sha256:d0533f473a46b916e6db6e84e20b06d8a70656600a0c14e819b0760b63f70226
+mock==2.0.0 \
+ --hash=sha256:5ce3c71c5545b472da17b72268978914d0252980348636840bd34a00b5cc96c1 \
+ --hash=sha256:b158b6df76edd239b8208d481dc46b6afd45a846b7812ff0ce58971cf5bc8bba
+more-itertools==4.1.0 \
+ --hash=sha256:0dd8f72eeab0d2c3bd489025bb2f6a1b8342f9b198f6fc37b52d15cfa4531fea \
+ --hash=sha256:11a625025954c20145b37ff6309cd54e39ca94f72f6bb9576d1195db6fa2442e \
+ --hash=sha256:c9ce7eccdcb901a2c75d326ea134e0886abfbea5f93e91cc95de9507c0816c44 \
+ # via pytest
+pbr==4.0.3 \
+ --hash=sha256:680bf5ba9b28dd56e08eb7c267991a37c7a5f90a92c2e07108829931a50ff80a \
+ --hash=sha256:6874feb22334a1e9a515193cba797664e940b763440c88115009ec323a7f2df5 \
+ # via mock
+pluggy==0.6.0 \
+ --hash=sha256:7f8ae7f5bdf75671a718d2daf0a64b7885f74510bcd98b1a0bb420eb9a9d0cff \
+ --hash=sha256:d345c8fe681115900d6da8d048ba67c25df42973bda370783cd58826442dcd7c \
+ --hash=sha256:e160a7fcf25762bb60efc7e171d4497ff1d8d2d75a3d0df7a21b76821ecbf5c5 \
+ # via pytest
+py==1.5.3 \
+ --hash=sha256:29c9fab495d7528e80ba1e343b958684f4ace687327e6f789a94bf3d1915f881 \
+ --hash=sha256:983f77f3331356039fdd792e9220b7b8ee1aa6bd2b25f567a963ff1de5a64f6a \
+ # via pytest
+pytest-forked==0.2 \
+ --hash=sha256:e4500cd0509ec4a26535f7d4112a8cc0f17d3a41c29ffd4eab479d2a55b30805 \
+ --hash=sha256:f275cb48a73fc61a6710726348e1da6d68a978f0ec0c54ece5a5fae5977e5a08 \
+ # via pytest-xdist
+pytest-xdist==1.22.2 \
+ --hash=sha256:be2662264b035920ba740ed6efb1c816a83c8a22253df7766d129f6a7bfdbd35 \
+ --hash=sha256:e8f5744acc270b3e7d915bdb4d5f471670f049b6fbd163d4cbd52203b075d30f
+pytest==3.5.1 \
+ --hash=sha256:54713b26c97538db6ff0703a12b19aeaeb60b5e599de542e7fca0ec83b9038e8 \
+ --hash=sha256:829230122facf05a5f81a6d4dfe6454a04978ea3746853b2b84567ecf8e5c526
+six==1.11.0 \
+ --hash=sha256:70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9 \
+ --hash=sha256:832dc0e10feb1aa2c68dcc57dbb658f1c7e65b9b61af69048abc87a2db00a0eb \
+ # via mock, more-itertools, pytest
diff --git a/uv/spec/fixtures/requirements/uv_pip_compile_imports_setup.txt b/uv/spec/fixtures/requirements/uv_pip_compile_imports_setup.txt
new file mode 100644
index 00000000000..48b89a02773
--- /dev/null
+++ b/uv/spec/fixtures/requirements/uv_pip_compile_imports_setup.txt
@@ -0,0 +1,19 @@
+# This file was autogenerated by uv via the following command:
+# uv pip compile --output-file something.txt something.in
+-e file:///Users/greysteil/code/python-test
+apipkg==1.5 # via execnet
+atomicwrites==1.2.1 # via pytest
+attrs==18.2.0
+contextlib2==0.5.5 # via raven
+execnet==1.5.0 # via pytest-xdist
+flaky==3.4.0
+mock==2.0.0
+more-itertools==4.3.0 # via pytest
+pbr==4.0.2 # via mock
+pluggy==0.7.1 # via pytest
+py==1.6.0 # via pytest
+pytest-forked==0.2 # via pytest-xdist
+pytest-xdist==1.23.0
+pytest==3.7.4
+raven==5.32.0
+six==1.11.0 # via mock, more-itertools, pytest, pytest-xdist
diff --git a/uv/spec/fixtures/requirements/uv_pip_compile_no_binary.txt b/uv/spec/fixtures/requirements/uv_pip_compile_no_binary.txt
new file mode 100644
index 00000000000..258ce1fdfa9
--- /dev/null
+++ b/uv/spec/fixtures/requirements/uv_pip_compile_no_binary.txt
@@ -0,0 +1,5 @@
+# This file was autogenerated by uv via the following command:
+# uv pip compile --output-file requirements.txt requirements.in
+--no-binary psycopg2
+
+psycopg2==2.7.4
diff --git a/uv/spec/fixtures/requirements/uv_pip_compile_no_strip_extras.txt b/uv/spec/fixtures/requirements/uv_pip_compile_no_strip_extras.txt
new file mode 100644
index 00000000000..e26439ba89b
--- /dev/null
+++ b/uv/spec/fixtures/requirements/uv_pip_compile_no_strip_extras.txt
@@ -0,0 +1,18 @@
+# This file was autogenerated by uv via the following command:
+# uv pip compile --no-strip-extras --output-file=constraints.txt constraints.in
+cachecontrol==0.12.10
+ # via -r constraints.in
+certifi==2021.10.8
+ # via requests
+charset-normalizer==2.0.7
+ # via requests
+idna==3.3
+ # via requests
+lockfile==0.12.2
+ # via cachecontrol
+msgpack==1.0.2
+ # via cachecontrol
+requests==2.26.0
+ # via cachecontrol
+urllib3==1.26.7
+ # via requests
diff --git a/uv/spec/fixtures/requirements/uv_pip_compile_safe.txt b/uv/spec/fixtures/requirements/uv_pip_compile_safe.txt
new file mode 100644
index 00000000000..51514461813
--- /dev/null
+++ b/uv/spec/fixtures/requirements/uv_pip_compile_safe.txt
@@ -0,0 +1,6 @@
+# This file was autogenerated by uv via the following command:
+# uv pip compile --output-file dev-requirements.txt dev-requirements.in
+flake8==3.5.0
+mccabe==0.6.1 # via flake8
+pycodestyle==2.4.0 # via flake8
+pyflakes==2.0.0 # via flake8
diff --git a/uv/spec/fixtures/requirements/uv_pip_compile_strip_extras.txt b/uv/spec/fixtures/requirements/uv_pip_compile_strip_extras.txt
new file mode 100644
index 00000000000..7c21fe5e458
--- /dev/null
+++ b/uv/spec/fixtures/requirements/uv_pip_compile_strip_extras.txt
@@ -0,0 +1,18 @@
+# This file was autogenerated by uv via the following command:
+# uv pip compile --output-file=constraints.txt constraints.in
+cachecontrol==0.12.10
+ # via -r constraints.in
+certifi==2021.10.8
+ # via requests
+charset-normalizer==2.0.7
+ # via requests
+idna==3.3
+ # via requests
+lockfile==0.12.2
+ # via cachecontrol
+msgpack==1.0.2
+ # via cachecontrol
+requests==2.26.0
+ # via cachecontrol
+urllib3==1.26.7
+ # via requests
diff --git a/uv/spec/fixtures/requirements/uv_pip_compile_unmet_marker.txt b/uv/spec/fixtures/requirements/uv_pip_compile_unmet_marker.txt
new file mode 100644
index 00000000000..cd2d87df5fc
--- /dev/null
+++ b/uv/spec/fixtures/requirements/uv_pip_compile_unmet_marker.txt
@@ -0,0 +1,15 @@
+# This file was autogenerated by uv via the following command:
+# uv pip compile --output-file=requirements.txt requirements.in
+apipkg==1.5 # via execnet
+atomicwrites==1.1.5 # via pytest
+attrs==17.3.0
+execnet==1.5.0 # via pytest-xdist
+mock==2.0.0
+more-itertools==4.3.0 # via pytest
+pbr==4.2.0 # via mock
+pluggy==0.7.1 # via pytest
+py==1.5.4 # via pytest
+pytest-forked==0.2 # via pytest-xdist
+pytest-xdist==1.22.5
+pytest==3.7.2
+six==1.11.0 # via mock, more-itertools, pytest, pytest-xdist
diff --git a/uv/spec/fixtures/requirements/uv_pip_compile_unpinned.txt b/uv/spec/fixtures/requirements/uv_pip_compile_unpinned.txt
new file mode 100644
index 00000000000..a776c740896
--- /dev/null
+++ b/uv/spec/fixtures/requirements/uv_pip_compile_unpinned.txt
@@ -0,0 +1,15 @@
+# This file was autogenerated by uv via the following command:
+# uv pip compile --output-file=requirements/test.txt requirements/test.in
+apipkg==1.4 # via execnet
+attrs==17.3.0
+execnet==1.5.0 # via pytest-xdist
+flaky==3.4.0
+mock==2.0.0
+more-itertools==4.1.0 # via pytest
+pbr==4.0.2 # via mock
+pluggy==0.6.0 # via pytest
+py==1.5.3 # via pytest
+pytest-forked==0.2 # via pytest-xdist
+pytest-xdist==1.22.2
+pytest==3.5.1
+six==1.11.0 # via mock, more-itertools, pytest
diff --git a/uv/spec/fixtures/requirements/uv_pip_compile_unpinned_renamed.txt b/uv/spec/fixtures/requirements/uv_pip_compile_unpinned_renamed.txt
new file mode 100644
index 00000000000..5c455cda2c8
--- /dev/null
+++ b/uv/spec/fixtures/requirements/uv_pip_compile_unpinned_renamed.txt
@@ -0,0 +1,15 @@
+# This file was autogenerated by uv via the following command:
+# uv pip compile --output-file=requirements/test-funky.txt requirements/test.in
+apipkg==1.4 # via execnet
+attrs==17.3.0
+execnet==1.5.0 # via pytest-xdist
+flaky==3.4.0
+mock==2.0.0
+more-itertools==4.1.0 # via pytest
+pbr==4.0.2 # via mock
+pluggy==0.6.0 # via pytest
+py==1.5.3 # via pytest
+pytest-forked==0.2 # via pytest-xdist
+pytest-xdist==1.22.2
+pytest==3.5.1
+six==1.11.0 # via mock, more-itertools, pytest
diff --git a/uv/spec/fixtures/requirements/uv_pip_compile_unsafe.txt b/uv/spec/fixtures/requirements/uv_pip_compile_unsafe.txt
new file mode 100644
index 00000000000..c037e652c06
--- /dev/null
+++ b/uv/spec/fixtures/requirements/uv_pip_compile_unsafe.txt
@@ -0,0 +1,10 @@
+# This file was autogenerated by uv via the following command:
+# uv pip compile --output-file dev-requirements.txt dev-requirements.in
+
+flake8==3.5.0
+mccabe==0.6.1 # via flake8
+pycodestyle==2.4.0 # via flake8
+pyflakes==2.0.0 # via flake8
+
+# The following packages are considered to be unsafe by pip-compile by default, but not by uv, in a requirements file:
+setuptools==40.4.3 # via flake8
diff --git a/uv/spec/fixtures/requirements/uv_pip_compile_vcs_url.txt b/uv/spec/fixtures/requirements/uv_pip_compile_vcs_url.txt
new file mode 100644
index 00000000000..3a0ace2a81b
--- /dev/null
+++ b/uv/spec/fixtures/requirements/uv_pip_compile_vcs_url.txt
@@ -0,0 +1,6 @@
+# This file was autogenerated by uv via the following command:
+# uv pip compile --output-file req.txt req.in
+mock @ git+https://github.com/testing-cabal/mock.git@286792b2cd5b5baa8338260538ed207391280e34
+attrs==17.3.0
+pbr==5.1.1
+six==1.12.0
diff --git a/uv/spec/fixtures/requirements/version_between_bounds.txt b/uv/spec/fixtures/requirements/version_between_bounds.txt
new file mode 100644
index 00000000000..8e68b1a1096
--- /dev/null
+++ b/uv/spec/fixtures/requirements/version_between_bounds.txt
@@ -0,0 +1,2 @@
+psycopg2==2.6.1, <=3.0.0
+luigi==2.2.0
diff --git a/uv/spec/fixtures/requirements/version_not_specified.txt b/uv/spec/fixtures/requirements/version_not_specified.txt
new file mode 100644
index 00000000000..bae1705b80a
--- /dev/null
+++ b/uv/spec/fixtures/requirements/version_not_specified.txt
@@ -0,0 +1,2 @@
+psycopg2
+luigi==2.2.0
diff --git a/uv/spec/fixtures/requirements/version_not_specified_dev.txt b/uv/spec/fixtures/requirements/version_not_specified_dev.txt
new file mode 100644
index 00000000000..e0af74c9976
--- /dev/null
+++ b/uv/spec/fixtures/requirements/version_not_specified_dev.txt
@@ -0,0 +1,3 @@
+-i https://pypi.org/simple
+py==1.5.2
+pytest==3.2.3
diff --git a/uv/spec/fixtures/requirements/version_not_specified_runtime.txt b/uv/spec/fixtures/requirements/version_not_specified_runtime.txt
new file mode 100644
index 00000000000..5c253e995fc
--- /dev/null
+++ b/uv/spec/fixtures/requirements/version_not_specified_runtime.txt
@@ -0,0 +1,6 @@
+-i https://pypi.org/simple
+certifi==2017.11.5
+chardet==3.0.4
+idna==2.5
+requests==2.18.0
+urllib3==1.21.1
diff --git a/uv/spec/fixtures/requirements/version_specified.txt b/uv/spec/fixtures/requirements/version_specified.txt
new file mode 100644
index 00000000000..05c5540856c
--- /dev/null
+++ b/uv/spec/fixtures/requirements/version_specified.txt
@@ -0,0 +1,5 @@
+psycopg2==2.6.1
+luigi==2.2.0
+pytest==3.4.0
+aiocache[redis]==0.10.0
+attrs==18.0.0
diff --git a/uv/spec/fixtures/requirements/version_urlib_patched.txt b/uv/spec/fixtures/requirements/version_urlib_patched.txt
new file mode 100644
index 00000000000..e555f0f4ed9
--- /dev/null
+++ b/uv/spec/fixtures/requirements/version_urlib_patched.txt
@@ -0,0 +1 @@
+urllib3==1.25.3
diff --git a/uv/spec/fixtures/requirements/version_urlib_vulnerable.txt b/uv/spec/fixtures/requirements/version_urlib_vulnerable.txt
new file mode 100644
index 00000000000..98e57c34244
--- /dev/null
+++ b/uv/spec/fixtures/requirements/version_urlib_vulnerable.txt
@@ -0,0 +1 @@
+urllib3==1.22
diff --git a/uv/spec/fixtures/requirements/with_constraints.txt b/uv/spec/fixtures/requirements/with_constraints.txt
new file mode 100644
index 00000000000..dfe9283f2f2
--- /dev/null
+++ b/uv/spec/fixtures/requirements/with_constraints.txt
@@ -0,0 +1,2 @@
+requests
+-c constraints.txt
diff --git a/uv/spec/fixtures/requirements/with_git_dependency.txt b/uv/spec/fixtures/requirements/with_git_dependency.txt
new file mode 100644
index 00000000000..c261be61af6
--- /dev/null
+++ b/uv/spec/fixtures/requirements/with_git_dependency.txt
@@ -0,0 +1,2 @@
+psycopg2==2.6.1
+git+https://github.com/requests/requests#egg=requests
diff --git a/uv/spec/fixtures/requirements/with_path_dependency.txt b/uv/spec/fixtures/requirements/with_path_dependency.txt
new file mode 100644
index 00000000000..1d11207711b
--- /dev/null
+++ b/uv/spec/fixtures/requirements/with_path_dependency.txt
@@ -0,0 +1,2 @@
+psycopg2==2.6.1
+file:.#egg=bowtie-json-schema
diff --git a/uv/spec/fixtures/requirements/with_setup_path.txt b/uv/spec/fixtures/requirements/with_setup_path.txt
new file mode 100644
index 00000000000..35618910290
--- /dev/null
+++ b/uv/spec/fixtures/requirements/with_setup_path.txt
@@ -0,0 +1,2 @@
+-e .
+requests==2.1.0
diff --git a/uv/spec/fixtures/setup_files/extras.cfg b/uv/spec/fixtures/setup_files/extras.cfg
new file mode 100644
index 00000000000..1b5c2078a8d
--- /dev/null
+++ b/uv/spec/fixtures/setup_files/extras.cfg
@@ -0,0 +1,23 @@
+[metadata]
+name = python-package
+version = 0.0
+description = Example setup.cfg
+url = httos://github.com/example/python-package
+author = Dependabot
+
+[options]
+packages = find:
+setup_requires =
+ numpy==1.11.0
+ pytest-runner
+install_requires =
+ requests[security] == 2.12.*
+ scipy==0.18.1
+ scikit-learn==0.18.1
+
+tests_require =
+ pytest==2.9.1
+ responses==0.5.1
+
+[options.extras_require]
+API = flask==0.12.2
diff --git a/uv/spec/fixtures/setup_files/extras.py b/uv/spec/fixtures/setup_files/extras.py
new file mode 100644
index 00000000000..d0a93ebbde1
--- /dev/null
+++ b/uv/spec/fixtures/setup_files/extras.py
@@ -0,0 +1,37 @@
+from pathlib import Path
+
+from setuptools import find_packages, setup
+
+from unidown import static_data
+
+# get long description
+with Path('README.rst').open(mode='r', encoding='UTF-8') as reader:
+ long_description = reader.read()
+
+setup(
+ name=static_data.NAME,
+ version=static_data.VERSION,
+ description='Example setup.py',
+ url='httos://github.com/example/python-package',
+ author='Dependabot',
+ scripts=[],
+ packages=find_packages(),
+ setup_requires=[
+ 'numpy==1.11.0',
+ 'pytest-runner',
+ ],
+ install_requires=[
+ 'requests[security] == 2.12.*',
+ 'scipy==0.18.1',
+ 'scikit-learn==0.18.1',
+ ],
+ tests_require=[
+ 'pytest==2.9.1',
+ 'responses==0.5.1',
+ ],
+ extras_require=dict(
+ API=[
+ 'flask==0.12.2',
+ ],
+ ),
+)
diff --git a/uv/spec/fixtures/setup_files/illformed_req.cfg b/uv/spec/fixtures/setup_files/illformed_req.cfg
new file mode 100644
index 00000000000..a07d919e87f
--- /dev/null
+++ b/uv/spec/fixtures/setup_files/illformed_req.cfg
@@ -0,0 +1,29 @@
+[metadata]
+name = python-package
+version = 0.0
+description = Example setup.cfg
+url = httos://github.com/example/python-package
+author = Dependabot
+
+[options]
+packages = find:
+setup_requires =
+ numpy==1.11.0
+ pytest-runner
+install_requires =
+ boto3==1.3.1
+ flake8 > 2.5.4, < 3.0.0
+ gocardless_pro
+ pandas==0.19.2
+ pep8==1.7.0
+ psycopg2==2.6.1raven == 5.32.0
+ requests==2.12.*
+ scipy==0.18.1
+ scikit-learn==0.18.1
+
+tests_require =
+ pytest==2.9.1
+ responses==0.5.1
+
+[options.extras_require]
+API = flask==0.12.2
diff --git a/uv/spec/fixtures/setup_files/illformed_req.py b/uv/spec/fixtures/setup_files/illformed_req.py
new file mode 100644
index 00000000000..e21f0c616c1
--- /dev/null
+++ b/uv/spec/fixtures/setup_files/illformed_req.py
@@ -0,0 +1,35 @@
+from setuptools import setup, find_packages
+
+setup(name='python-package',
+ version='0.0',
+ description='Example setup.py',
+ url='httos://github.com/example/python-package',
+ author='Dependabot',
+ scripts=[],
+ packages=find_packages(),
+ setup_requires=[
+ 'numpy==1.11.0',
+ 'pytest-runner',
+ ],
+ install_requires=[
+ 'boto3==1.3.1',
+ 'flake8 > 2.5.4, < 3.0.0',
+ 'gocardless_pro',
+ 'pandas==0.19.2',
+ 'pep8==1.7.0',
+ 'psycopg2==2.6.1'
+ 'raven==5.32.0',
+ 'requests==2.12.*',
+ 'scipy==0.18.1',
+ 'scikit-learn==0.18.1',
+ ],
+ tests_require=[
+ 'pytest==2.9.1',
+ 'responses==0.5.1',
+ ],
+ extras_require=dict(
+ API=[
+ 'flask==0.12.2',
+ ],
+ ),
+)
diff --git a/uv/spec/fixtures/setup_files/imports_version.py b/uv/spec/fixtures/setup_files/imports_version.py
new file mode 100644
index 00000000000..b981326f395
--- /dev/null
+++ b/uv/spec/fixtures/setup_files/imports_version.py
@@ -0,0 +1,33 @@
+from setuptools import setup, find_packages
+
+from split_settings import __version__
+
+setup(name='python-package',
+ version=__version__,
+ description='Example setup.py',
+ url='httos://github.com/example/python-package',
+ author='Dependabot',
+ scripts=[],
+ packages=find_packages(),
+ setup_requires=[
+ 'numpy==1.11.0',
+ 'pytest-runner',
+ ],
+ install_requires=[
+ 'boto3==1.3.1',
+ 'flake8 > 2.5.4, < 3.0.0',
+ 'gocardless_pro',
+ 'numpy>=1.11.0',
+ 'pandas==0.19.2',
+ 'pep8==1.7.0',
+ 'psycopg2==2.6.1',
+ 'raven == 5.32.0',
+ 'requests==2.12.*',
+ 'scipy==0.18.1',
+ 'scikit-learn==0.18.1',
+ ],
+ tests_require=[
+ 'pytest==2.9.1',
+ 'responses==0.5.1',
+ ]
+ )
diff --git a/uv/spec/fixtures/setup_files/imports_version_for_dep.py b/uv/spec/fixtures/setup_files/imports_version_for_dep.py
new file mode 100644
index 00000000000..a6c78c4b1e9
--- /dev/null
+++ b/uv/spec/fixtures/setup_files/imports_version_for_dep.py
@@ -0,0 +1,34 @@
+from setuptools import setup, find_packages
+
+from split_settings import __version__
+
+setup(name='python-package',
+ version=__version__,
+ description='Example setup.py',
+ url='httos://github.com/example/python-package',
+ author='Dependabot',
+ scripts=[],
+ packages=find_packages(),
+ setup_requires=[
+ 'numpy==1.11.0',
+ 'pytest-runner',
+ ],
+ install_requires=[
+ 'acme=={0}'.format(__version__),
+ 'boto3==1.3.1',
+ 'flake8 > 2.5.4, < 3.0.0',
+ 'gocardless_pro',
+ 'numpy>=1.11.0',
+ 'pandas==0.19.2',
+ 'pep8==1.7.0',
+ 'psycopg2==2.6.1',
+ 'raven == 5.32.0',
+ 'requests==2.12.*',
+ 'scipy==0.18.1',
+ 'scikit-learn==0.18.1',
+ ],
+ tests_require=[
+ 'pytest==2.9.1',
+ 'responses==0.5.1',
+ ]
+ )
diff --git a/uv/spec/fixtures/setup_files/impossible_imports.py b/uv/spec/fixtures/setup_files/impossible_imports.py
new file mode 100644
index 00000000000..4d49f73c993
--- /dev/null
+++ b/uv/spec/fixtures/setup_files/impossible_imports.py
@@ -0,0 +1,66 @@
+#!/usr/bin/env python
+from pathlib import Path
+
+from setuptools import find_packages, setup
+
+from unidown import static_data
+
+# get long description
+with Path('README.rst').open(mode='r', encoding='UTF-8') as reader:
+ long_description = reader.read()
+
+setup(
+ name=static_data.NAME,
+ version=static_data.VERSION,
+ description=static_data.DESCRIPTION,
+ long_description=long_description,
+ author=static_data.AUTHOR,
+ author_email=static_data.AUTHOR_EMAIL,
+ license='GPLv3',
+ url=static_data.PROJECT_URL,
+ classifiers=[
+ 'Programming Language :: Python :: 3.7',
+ 'License :: OSI Approved :: GNU General Public License v3 (GPLv3)',
+ 'Development Status :: 4 - Beta',
+ 'Operating System :: OS Independent',
+ 'Intended Audience :: Developers',
+ 'Intended Audience :: End Users/Desktop',
+ 'Natural Language :: English',
+ 'Environment :: Console',
+ # 'Environment :: X11 Applications :: Qt',
+ ],
+ keywords='modular downloader',
+ packages=find_packages(include=['unidown', 'unidown.*']),
+ python_requires='>=3.7',
+ install_requires=[
+ 'urllib3[secure]==1.23',
+ 'tqdm==4.25.0',
+ 'protobuf==3.6.1',
+ 'packaging==17.1',
+ ],
+ extras_require={
+ 'dev': [
+ 'prospector[with_everything]==1.1.2',
+ 'nose2[coverage_plugin]==0.8.0',
+ 'Sphinx==1.7.7',
+ 'sphinxcontrib-svg2pdfconverter==0.1.0',
+ 'sphinx_rtd_theme==0.4.1',
+ 'twine==1.11.0',
+ 'setuptools==40.2.0',
+ 'wheel==0.31.1',
+ ],
+ },
+ package_data={
+
+ },
+ include_package_data=True,
+ zip_safe=True,
+ entry_points={
+ 'console_scripts': [
+ 'unidown = unidown.main:main',
+ ],
+ # 'gui_scripts': [
+ # '???',
+ # ],
+ },
+)
diff --git a/uv/spec/fixtures/setup_files/markers.cfg b/uv/spec/fixtures/setup_files/markers.cfg
new file mode 100644
index 00000000000..0163ee9ac6b
--- /dev/null
+++ b/uv/spec/fixtures/setup_files/markers.cfg
@@ -0,0 +1,31 @@
+[metadata]
+name = python-package
+version = 0.0
+description = Example setup.cfg
+url = httos://github.com/example/python-package
+author = Dependabot
+
+[options]
+packages = find:
+setup_requires =
+ numpy==1.11.0
+ pytest-runner
+install_requires =
+ boto3==1.3.1;python_version<="2.6"
+ boto3==1.3.1;python_version>="2.7"
+ flake8 > 2.5.4, < 3.0.0
+ gocardless_pro
+ pandas==0.19.2
+ pep8==1.7.0
+ psycopg2==2.6.1
+ raven == 5.32.0
+ requests==2.12.*
+ scipy==0.18.1
+ scikit-learn==0.18.1
+
+tests_require =
+ pytest==2.9.1
+ responses==0.5.1
+
+[options.extras_require]
+API = flask==0.12.2
diff --git a/uv/spec/fixtures/setup_files/markers.py b/uv/spec/fixtures/setup_files/markers.py
new file mode 100644
index 00000000000..1c2a23e9427
--- /dev/null
+++ b/uv/spec/fixtures/setup_files/markers.py
@@ -0,0 +1,36 @@
+from setuptools import setup, find_packages
+
+setup(name='python-package',
+ version='0.0',
+ description='Example setup.py',
+ url='httos://github.com/example/python-package',
+ author='Dependabot',
+ scripts=[],
+ packages=find_packages(),
+ setup_requires=[
+ 'numpy==1.11.0',
+ 'pytest-runner',
+ ],
+ install_requires=[
+ 'boto3==1.0.1;python_version<="2.6"',
+ 'boto3==1.3.1;python_version>="2.7"',
+ 'flake8 > 2.5.4, < 3.0.0',
+ 'gocardless_pro',
+ 'pandas==0.19.2',
+ 'pep8==1.7.0',
+ 'psycopg2==2.6.1',
+ 'raven == 5.32.0',
+ 'requests==2.12.*',
+ 'scipy==0.18.1',
+ 'scikit-learn==0.18.1',
+ ],
+ tests_require=[
+ 'pytest==2.9.1',
+ 'responses==0.5.1',
+ ],
+ extras_require=dict(
+ API=[
+ 'flask==0.12.2',
+ ],
+ ),
+)
diff --git a/uv/spec/fixtures/setup_files/no_tests_require.cfg b/uv/spec/fixtures/setup_files/no_tests_require.cfg
new file mode 100644
index 00000000000..dcc0de1ce0d
--- /dev/null
+++ b/uv/spec/fixtures/setup_files/no_tests_require.cfg
@@ -0,0 +1,23 @@
+[metadata]
+name = python-package
+version = 0.0
+description = Example setup.cfg
+url = httos://github.com/example/python-package
+author = Dependabot
+
+[options]
+packages = find:
+setup_requires =
+ numpy==1.11.0
+ pytest-runner
+install_requires =
+ boto3==1.3.1
+ flake8 > 2.5.4, < 3.0.0
+ gocardless_pro
+ pandas==0.19.2
+ pep8==1.7.0
+ psycopg2==2.6.1
+ raven == 5.32.0
+ requests==2.12.*
+ scipy==0.18.1
+ scikit-learn==0.18.1
diff --git a/uv/spec/fixtures/setup_files/no_tests_require.py b/uv/spec/fixtures/setup_files/no_tests_require.py
new file mode 100644
index 00000000000..bef8a498f49
--- /dev/null
+++ b/uv/spec/fixtures/setup_files/no_tests_require.py
@@ -0,0 +1,27 @@
+from setuptools import setup, find_packages
+
+setup(name='python-package',
+ version='0.0',
+ description='Example setup.py',
+ url='httos://github.com/example/python-package',
+ author='Dependabot',
+ scripts=[],
+ packages=find_packages(),
+ setup_requires=[
+ 'numpy==1.11.0',
+ 'pytest-runner',
+ ],
+ install_requires=[
+ 'boto3==1.3.1',
+ 'flake8==2.5.4',
+ 'gocardless_pro==0.2.3',
+ 'numpy==1.11.0',
+ 'pandas==0.19.2',
+ 'pep8==1.7.0',
+ 'psycopg2==2.6.1',
+ 'raven==5.32.0',
+ 'requests==2.12.4',
+ 'scipy==0.18.1',
+ 'scikit-learn==0.18.1',
+ ]
+ )
diff --git a/uv/spec/fixtures/setup_files/requests_setup.py b/uv/spec/fixtures/setup_files/requests_setup.py
new file mode 100644
index 00000000000..e3bc8761c44
--- /dev/null
+++ b/uv/spec/fixtures/setup_files/requests_setup.py
@@ -0,0 +1,101 @@
+#!/usr/bin/env python
+# Learn more: https://github.com/kennethreitz/setup.py
+
+import os
+import re
+import sys
+
+from codecs import open
+
+from setuptools import setup
+from setuptools.command.test import test as TestCommand
+
+here = os.path.abspath(os.path.dirname(__file__))
+
+class PyTest(TestCommand):
+ user_options = [('pytest-args=', 'a', "Arguments to pass into py.test")]
+
+ def initialize_options(self):
+ TestCommand.initialize_options(self)
+ try:
+ from multiprocessing import cpu_count
+ self.pytest_args = ['-n', str(cpu_count()), '--boxed']
+ except (ImportError, NotImplementedError):
+ self.pytest_args = ['-n', '1', '--boxed']
+
+ def finalize_options(self):
+ TestCommand.finalize_options(self)
+ self.test_args = []
+ self.test_suite = True
+
+ def run_tests(self):
+ import pytest
+
+ errno = pytest.main(self.pytest_args)
+ sys.exit(errno)
+
+# 'setup.py publish' shortcut.
+if sys.argv[-1] == 'publish':
+ os.system('python setup.py sdist bdist_wheel')
+ os.system('twine upload dist/*')
+ sys.exit()
+
+packages = ['requests']
+
+requires = [
+ 'chardet>=3.0.2,<3.1.0',
+ 'idna>=2.5,<2.7',
+ 'urllib3>=1.21.1,<1.23',
+ 'certifi>=2017.4.17'
+
+]
+test_requirements = ['pytest-httpbin==0.0.7', 'pytest-cov', 'pytest-mock', 'pytest-xdist', 'PySocks>=1.5.6, !=1.5.7', 'pytest>=2.8.0']
+
+about = {}
+with open(os.path.join(here, 'requests', '__version__.py'), 'r', 'utf-8') as f:
+ exec(f.read(), about)
+
+with open('README.rst', 'r', 'utf-8') as f:
+ readme = f.read()
+with open('HISTORY.rst', 'r', 'utf-8') as f:
+ history = f.read()
+
+setup(
+ name=about['__title__'],
+ version=about['__version__'],
+ description=about['__description__'],
+ long_description=readme + '\n\n' + history,
+ author=about['__author__'],
+ author_email=about['__author_email__'],
+ url=about['__url__'],
+ packages=packages,
+ package_data={'': ['LICENSE', 'NOTICE'], 'requests': ['*.pem']},
+ package_dir={'requests': 'requests'},
+ include_package_data=True,
+ install_requires=requires,
+ license=about['__license__'],
+ zip_safe=False,
+ classifiers=(
+ 'Development Status :: 5 - Production/Stable',
+ 'Intended Audience :: Developers',
+ 'Natural Language :: English',
+ 'License :: OSI Approved :: Apache Software License',
+ 'Programming Language :: Python',
+ 'Programming Language :: Python :: 2',
+ 'Programming Language :: Python :: 2.6',
+ 'Programming Language :: Python :: 2.7',
+ 'Programming Language :: Python :: 3',
+ 'Programming Language :: Python :: 3.4',
+ 'Programming Language :: Python :: 3.5',
+ 'Programming Language :: Python :: 3.6',
+ 'Programming Language :: Python :: Implementation :: CPython',
+ 'Programming Language :: Python :: Implementation :: PyPy'
+ ),
+ cmdclass={'test': PyTest},
+ tests_require=test_requirements,
+ extras_require={
+ 'security': ['pyOpenSSL>=0.14', 'cryptography>=1.3.4', 'idna>=2.0.0'],
+ 'socks': ['PySocks>=1.5.6, !=1.5.7'],
+ 'socks:sys_platform == "win32" and (python_version == "2.7" or python_version == "2.6")': ['win_inet_pton'],
+ },
+)
diff --git a/uv/spec/fixtures/setup_files/requires_main.py b/uv/spec/fixtures/setup_files/requires_main.py
new file mode 100644
index 00000000000..25a69b1d3d7
--- /dev/null
+++ b/uv/spec/fixtures/setup_files/requires_main.py
@@ -0,0 +1,29 @@
+import setuptools
+
+def _main():
+ setuptools.setup(name='python-package',
+ version='0.0',
+ description='Example setup.py',
+ url='httos://github.com/example/python-package',
+ author='Dependabot',
+ scripts=[],
+ packages=setuptools.find_packages(),
+ setup_requires=[
+ 'pytest-runner',
+ ],
+ install_requires=[
+ 'raven == 5.32.0',
+ ],
+ tests_require=[
+ 'pytest==2.9.1',
+ 'responses==0.5.1',
+ ],
+ extras_require=dict(
+ API=[
+ 'flask==0.12.2',
+ ],
+ ),
+ )
+
+if __name__ == "__main__":
+ _main()
diff --git a/uv/spec/fixtures/setup_files/setup.cfg b/uv/spec/fixtures/setup_files/setup.cfg
new file mode 100644
index 00000000000..b3328ca4e30
--- /dev/null
+++ b/uv/spec/fixtures/setup_files/setup.cfg
@@ -0,0 +1,25 @@
+[metadata]
+name = pygerrit2
+summary = Client library for interacting with Gerrit's REST API
+author = David Pursehouse
+author-email = david.pursehouse@gmail.com
+home-page = https://github.com/dpursehouse/pygerrit2
+license = The MIT License
+description-file = description.rst
+keywords = gerrit rest http api client
+platform = POSIX, Unix, MacOS
+classifiers =
+ Development Status :: 5 - Production/Stable
+ Environment :: Console
+ Intended Audience :: Developers
+ Intended Audience :: Information Technology
+ License :: OSI Approved :: MIT License
+ Natural Language :: English
+ Programming Language :: Python
+ Programming Language :: Python :: 3.5
+ Programming Language :: Python :: 3.6
+ Programming Language :: Python :: 3.7
+ Operating System :: POSIX
+ Operating System :: Unix
+ Operating System :: MacOS
+ Topic :: Software Development :: Libraries :: Python Modules
diff --git a/uv/spec/fixtures/setup_files/setup.py b/uv/spec/fixtures/setup_files/setup.py
new file mode 100644
index 00000000000..ad731d44575
--- /dev/null
+++ b/uv/spec/fixtures/setup_files/setup.py
@@ -0,0 +1,35 @@
+from setuptools import setup, find_packages
+
+setup(name='python-package',
+ version='0.0',
+ description='Example setup.py',
+ url='httos://github.com/example/python-package',
+ author='Dependabot',
+ scripts=[],
+ packages=find_packages(),
+ setup_requires=[
+ 'numpy==1.11.0',
+ 'pytest-runner',
+ ],
+ install_requires=[
+ 'boto3==1.3.1',
+ 'flake8 > 2.5.4, < 3.0.0',
+ 'gocardless_pro',
+ 'pandas==0.19.2',
+ 'pep8==1.7.0',
+ 'psycopg2==2.6.1',
+ 'raven == 5.32.0',
+ 'requests==2.12.*',
+ 'scipy==0.18.1',
+ 'scikit-learn==0.18.1',
+ ],
+ tests_require=[
+ 'pytest==2.9.1',
+ 'responses==0.5.1',
+ ],
+ extras_require=dict(
+ API=[
+ 'flask==0.12.2',
+ ],
+ ),
+)
diff --git a/uv/spec/fixtures/setup_files/setup_with_requires.cfg b/uv/spec/fixtures/setup_files/setup_with_requires.cfg
new file mode 100644
index 00000000000..6ff01959226
--- /dev/null
+++ b/uv/spec/fixtures/setup_files/setup_with_requires.cfg
@@ -0,0 +1,30 @@
+[metadata]
+name = python-package
+version = 0.0
+description = Example setup.cfg
+url = httos://github.com/example/python-package
+author = Dependabot
+
+[options]
+packages = find:
+setup_requires =
+ numpy==1.11.0
+ pytest-runner
+install_requires =
+ boto3==1.3.1
+ flake8 > 2.5.4, < 3.0.0
+ gocardless_pro
+ pandas==0.19.2
+ pep8==1.7.0
+ psycopg2==2.6.1
+ raven == 5.32.0
+ requests==2.12.*
+ scipy==0.18.1
+ scikit-learn==0.18.1
+
+tests_require =
+ pytest==2.9.1
+ responses==0.5.1
+
+[options.extras_require]
+API = flask==0.12.2
diff --git a/uv/spec/fixtures/setup_files/small.py b/uv/spec/fixtures/setup_files/small.py
new file mode 100644
index 00000000000..297d3bf2e5f
--- /dev/null
+++ b/uv/spec/fixtures/setup_files/small.py
@@ -0,0 +1,26 @@
+from setuptools import setup, find_packages
+
+setup(name='python-package',
+ version='0.0',
+ description='Example setup.py',
+ url='httos://github.com/example/python-package',
+ author='Dependabot',
+ scripts=[],
+ packages=find_packages(),
+ setup_requires=[
+ 'pytest-runner',
+ ],
+ install_requires=[
+ 'raven == 5.32.0',
+ ],
+ tests_require=[
+ 'pytest==2.9.1',
+ 'responses==0.5.1',
+ ],
+ extras_require=dict(
+ API=[
+ 'flask==0.12.2',
+ ],
+ socks=['PySocks>=1.5.6, !=1.5.7'],
+ ),
+)
diff --git a/uv/spec/fixtures/setup_files/small_needs_sanitizing.py b/uv/spec/fixtures/setup_files/small_needs_sanitizing.py
new file mode 100644
index 00000000000..9683891d05f
--- /dev/null
+++ b/uv/spec/fixtures/setup_files/small_needs_sanitizing.py
@@ -0,0 +1,31 @@
+from setuptools import setup, find_packages
+
+file = open("some_file", "r")
+file.read()
+
+from split_settings import __version__
+
+setup(name='python-package',
+ version=__version__,
+ description='Example setup.py',
+ url='httos://github.com/example/python-package',
+ author='Dependabot',
+ scripts=[],
+ packages=find_packages(),
+ setup_requires=[
+ 'pytest-runner',
+ ],
+ install_requires=[
+ 'raven == 5.32.0',
+ ],
+ tests_require=[
+ 'pytest==2.9.1',
+ 'responses==0.5.1',
+ ],
+ extras_require=dict(
+ API=[
+ 'flask==0.12.2',
+ ],
+ socks=['PySocks>=1.5.6, !=1.5.7'],
+ ),
+)
diff --git a/uv/spec/fixtures/setup_files/unparseable_python_requires.py b/uv/spec/fixtures/setup_files/unparseable_python_requires.py
new file mode 100644
index 00000000000..de895297a9b
--- /dev/null
+++ b/uv/spec/fixtures/setup_files/unparseable_python_requires.py
@@ -0,0 +1,29 @@
+from setuptools import setup, find_packages
+
+MIN_PY_VERSION = '.'.join(map(str, hass_const.REQUIRED_PYTHON_VER))
+
+setup(name='python-package',
+ version='0.0',
+ description='Example setup.py',
+ url='httos://github.com/example/python-package',
+ author='Dependabot',
+ scripts=[],
+ packages=find_packages(),
+ setup_requires=[
+ 'pytest-runner',
+ ],
+ install_requires=[
+ 'raven == 5.32.0',
+ ],
+ tests_require=[
+ 'pytest==2.9.1',
+ 'responses==0.5.1',
+ ],
+ extras_require=dict(
+ API=[
+ 'flask==0.12.2',
+ ],
+ socks=['PySocks>=1.5.6, !=1.5.7'],
+ ),
+ python_requires='>={}'.format(MIN_PY_VERSION),
+)
diff --git a/uv/spec/fixtures/setup_files/with_comments.cfg b/uv/spec/fixtures/setup_files/with_comments.cfg
new file mode 100644
index 00000000000..5fd68484e35
--- /dev/null
+++ b/uv/spec/fixtures/setup_files/with_comments.cfg
@@ -0,0 +1,31 @@
+[metadata]
+name = python-package
+version = 0.0
+description = Example setup.cfg
+url = httos://github.com/example/python-package
+author = Dependabot
+
+[options]
+packages = find:
+setup_requires =
+ numpy==1.11.0
+ pytest-runner
+install_requires =
+ boto3==1.3.1 # this is a comment
+ flake8 > 2.5.4, < 3.0.0
+ gocardless_pro
+ pandas==0.19.2
+ pep8==1.7.0
+ psycopg2==2.6.1
+ # there is also a comment here
+ raven == 5.32.0
+ requests==2.12.*
+ scipy==0.18.1
+ scikit-learn==0.18.1
+
+tests_require =
+ pytest==2.9.1
+ responses==0.5.1
+
+[options.extras_require]
+API = flask==0.12.2
diff --git a/uv/spec/fixtures/setup_files/with_open.py b/uv/spec/fixtures/setup_files/with_open.py
new file mode 100644
index 00000000000..6f9e3988593
--- /dev/null
+++ b/uv/spec/fixtures/setup_files/with_open.py
@@ -0,0 +1,50 @@
+import codecs
+import io
+import os
+from setuptools import setup, find_packages
+
+file = open("some_file", "r")
+file.read()
+
+file2 = codecs.open("some_file", "r")
+file2.read()
+
+file3 = io.open("some_file", "r")
+file3.read()
+
+file4 = file('README.rst').read()
+
+def read(fname):
+ return open(os.path.join(os.path.dirname(__file__), fname)).read()
+
+read("soemthing")
+
+setup(name='python-package',
+ version='0.0',
+ description='Example setup.py',
+ url='httos://github.com/example/python-package',
+ author='Dependabot',
+ scripts=[],
+ packages=find_packages(),
+ setup_requires=[
+ 'numpy==1.11.0',
+ 'pytest-runner',
+ ],
+ install_requires=[
+ 'boto3==1.3.1',
+ 'flake8 > 2.5.4, < 3.0.0',
+ 'gocardless_pro',
+ 'numpy>=1.11.0',
+ 'pandas==0.19.2',
+ 'pep8==1.7.0',
+ 'psycopg2==2.6.1',
+ 'raven == 5.32.0',
+ 'requests==2.12.4',
+ 'scipy==0.18.1',
+ 'scikit-learn==0.18.1',
+ ],
+ tests_require=[
+ 'pytest==2.9.1',
+ 'responses==0.5.1',
+ ]
+ )
diff --git a/uv/spec/fixtures/setup_files/with_parse_reqs.py b/uv/spec/fixtures/setup_files/with_parse_reqs.py
new file mode 100644
index 00000000000..d9d62f97d40
--- /dev/null
+++ b/uv/spec/fixtures/setup_files/with_parse_reqs.py
@@ -0,0 +1,23 @@
+from pip._internal.network.session import PipSession
+from pip._internal.req.req_file import parse_requirements
+from setuptools import setup, find_packages
+
+reqs = [str(r.req) for r in parse_requirements('requirements.txt', session=PipSession()) if r.req is not None]
+
+setup(name='python-package',
+ version='0.0',
+ description='Example setup.py',
+ url='httos://github.com/example/python-package',
+ author='Dependabot',
+ scripts=[],
+ packages=find_packages(),
+ setup_requires=[
+ 'numpy==1.11.0',
+ 'pytest-runner',
+ ],
+ install_requires=reqs,
+ tests_require=[
+ 'pytest==2.9.1',
+ 'responses==0.5.1',
+ ]
+ )
diff --git a/uv/spec/fixtures/setup_files/with_pbr.py b/uv/spec/fixtures/setup_files/with_pbr.py
new file mode 100644
index 00000000000..9eef18bce2b
--- /dev/null
+++ b/uv/spec/fixtures/setup_files/with_pbr.py
@@ -0,0 +1,7 @@
+import setuptools
+
+setuptools.setup(
+ packages=setuptools.find_packages(),
+ install_requires=['raven'],
+ setup_requires=['pbr'],
+ pbr=True)
diff --git a/uv/spec/fixtures/setup_files/with_print.py b/uv/spec/fixtures/setup_files/with_print.py
new file mode 100644
index 00000000000..37359bd9899
--- /dev/null
+++ b/uv/spec/fixtures/setup_files/with_print.py
@@ -0,0 +1,37 @@
+from setuptools import setup, find_packages
+from distutils import log
+
+print("Installing some files")
+
+log.set_verbosity(log.DEBUG)
+log.info("Installing some files")
+
+setup(name='python-package',
+ version='0.0',
+ description='Example setup.py',
+ url='httos://github.com/example/python-package',
+ author='Dependabot',
+ scripts=[],
+ packages=find_packages(),
+ setup_requires=[
+ 'numpy==1.11.0',
+ 'pytest-runner',
+ ],
+ install_requires=[
+ 'boto3==1.3.1',
+ 'flake8 > 2.5.4, < 3.0.0',
+ 'gocardless_pro',
+ 'numpy>=1.11.0',
+ 'pandas==0.19.2',
+ 'pep8==1.7.0',
+ 'psycopg2==2.6.1',
+ 'raven == 5.32.0',
+ 'requests==2.12.4',
+ 'scipy==0.18.1',
+ 'scikit-learn==0.18.1',
+ ],
+ tests_require=[
+ 'pytest==2.9.1',
+ 'responses==0.5.1',
+ ]
+ )
diff --git a/uv/spec/spec_helper.rb b/uv/spec/spec_helper.rb
new file mode 100644
index 00000000000..958fb301fd4
--- /dev/null
+++ b/uv/spec/spec_helper.rb
@@ -0,0 +1,32 @@
+# typed: true
+# frozen_string_literal: true
+
+def common_dir
+ @common_dir ||= Gem::Specification.find_by_name("dependabot-common").gem_dir
+end
+
+def require_common_spec(path)
+ require "#{common_dir}/spec/dependabot/#{path}"
+end
+
+require "#{common_dir}/spec/spec_helper.rb"
+
+module SlowTestHelper
+ def self.slow_tests?
+ ENV["SUITE_NAME"] == "python_slow"
+ end
+end
+
+RSpec.configure do |config|
+ config.around do |example|
+ if SlowTestHelper.slow_tests? && example.metadata[:slow]
+ example.run
+ elsif !SlowTestHelper.slow_tests? && !example.metadata[:slow]
+ example.run
+ else
+ example.skip
+ end
+ end
+
+ config.profile_examples = 10
+end