Support extras statements in Python PDM cataloger (#4352)

* fix pdm

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* update json schema

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* fix tests

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* add test for metadata construction

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* add missing test fixture

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* conserve markers

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* update json schema

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* add additional tests

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

---------

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
This commit is contained in:
Alex Goodman 2025-11-14 15:13:10 -05:00 committed by GitHub
parent 6a21b5e5e2
commit 7bf7bcc461
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 6121 additions and 156 deletions

View File

@ -3,5 +3,9 @@ package internal
const ( const (
// JSONSchemaVersion is the current schema version output by the JSON encoder // JSONSchemaVersion is the current schema version output by the JSON encoder
// This is roughly following the "SchemaVer" guidelines for versioning the JSON schema. Please see schema/json/README.md for details on how to increment. // This is roughly following the "SchemaVer" guidelines for versioning the JSON schema. Please see schema/json/README.md for details on how to increment.
JSONSchemaVersion = "16.0.43" JSONSchemaVersion = "16.1.0"
// Changelog
// 16.1.0 - reformulated the python pdm fields (added "URL" and removed the unused "path" field).
) )

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
{ {
"$schema": "https://json-schema.org/draft/2020-12/schema", "$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "anchore.io/schema/syft/json/16.0.43/document", "$id": "anchore.io/schema/syft/json/16.1.0/document",
"$ref": "#/$defs/Document", "$ref": "#/$defs/Document",
"$defs": { "$defs": {
"AlpmDbEntry": { "AlpmDbEntry": {
@ -3300,6 +3300,23 @@
], ],
"description": "PythonPackage represents all captured data for a python egg or wheel package (specifically as outlined in the PyPA core metadata specification https://packaging.python.org/en/latest/specifications/core-metadata/)." "description": "PythonPackage represents all captured data for a python egg or wheel package (specifically as outlined in the PyPA core metadata specification https://packaging.python.org/en/latest/specifications/core-metadata/)."
}, },
"PythonPdmFileEntry": {
"properties": {
"url": {
"type": "string",
"description": "URL is the file download URL"
},
"digest": {
"$ref": "#/$defs/PythonFileDigest",
"description": "Digest is the hash digest of the file hosted at the URL"
}
},
"type": "object",
"required": [
"url",
"digest"
]
},
"PythonPdmLockEntry": { "PythonPdmLockEntry": {
"properties": { "properties": {
"summary": { "summary": {
@ -3308,27 +3325,75 @@
}, },
"files": { "files": {
"items": { "items": {
"$ref": "#/$defs/PythonFileRecord" "$ref": "#/$defs/PythonPdmFileEntry"
}, },
"type": "array", "type": "array",
"description": "Files are the package files with their paths and hash digests" "description": "Files are the package files with their paths and hash digests (for the base package without extras)"
},
"marker": {
"type": "string",
"description": "Marker is the \"environment\" --conditional expressions that determine whether a package should be installed based on the runtime environment"
},
"requiresPython": {
"type": "string",
"description": "RequiresPython specifies the Python version requirement (e.g., \"\u003e=3.6\")."
}, },
"dependencies": { "dependencies": {
"items": { "items": {
"type": "string" "type": "string"
}, },
"type": "array", "type": "array",
"description": "Dependencies are the dependency specifications, without environment qualifiers" "description": "Dependencies are the dependency specifications for the base package (without extras)"
},
"extras": {
"items": {
"$ref": "#/$defs/PythonPdmLockExtraVariant"
},
"type": "array",
"description": "Extras contains variants for different extras combinations (PDM may have multiple entries per package)"
} }
}, },
"type": "object", "type": "object",
"required": [ "required": [
"summary", "summary",
"files", "files"
"dependencies"
], ],
"description": "PythonPdmLockEntry represents a single package entry within a pdm.lock file." "description": "PythonPdmLockEntry represents a single package entry within a pdm.lock file."
}, },
"PythonPdmLockExtraVariant": {
"properties": {
"extras": {
"items": {
"type": "string"
},
"type": "array",
"description": "Extras are the optional extras enabled for this variant (e.g., [\"toml\"], [\"dev\"], or [\"toml\", \"dev\"])"
},
"dependencies": {
"items": {
"type": "string"
},
"type": "array",
"description": "Dependencies are the dependencies specific to this extras variant"
},
"files": {
"items": {
"$ref": "#/$defs/PythonPdmFileEntry"
},
"type": "array",
"description": "Files are the package files specific to this variant (only populated if different from base)"
},
"marker": {
"type": "string",
"description": "Marker is the environment conditional expression for this variant (e.g., \"python_version \u003c \\\"3.11\\\"\")"
}
},
"type": "object",
"required": [
"extras"
],
"description": "PythonPdmLockExtraVariant represents a specific extras combination variant within a PDM lock file."
},
"PythonPipRequirementsEntry": { "PythonPipRequirementsEntry": {
"properties": { "properties": {
"name": { "name": {

View File

@ -349,10 +349,10 @@ func Test_OriginatorSupplier(t *testing.T) {
name: "from python PDM lock", name: "from python PDM lock",
input: pkg.Package{ input: pkg.Package{
Metadata: pkg.PythonPdmLockEntry{ Metadata: pkg.PythonPdmLockEntry{
Files: []pkg.PythonFileRecord{ Files: []pkg.PythonPdmFileEntry{
{ {
Path: "", URL: "https://pypi.org/project/testpkg/1.2.3/file1.tar.gz",
Digest: &pkg.PythonFileDigest{ Digest: pkg.PythonFileDigest{
Algorithm: "sha256", Algorithm: "sha256",
Value: "3d5da6925056f6f18f119200434a4780a94263f10d1c21d032a6f6b2baa20651", Value: "3d5da6925056f6f18f119200434a4780a94263f10d1c21d032a6f6b2baa20651",
}, },

View File

@ -82,6 +82,63 @@ func packageRef(name, extra string) string {
return cleanName + "[" + cleanExtra + "]" return cleanName + "[" + cleanExtra + "]"
} }
func pdmLockDependencySpecifier(p pkg.Package) dependency.Specification {
meta, ok := p.Metadata.(pkg.PythonPdmLockEntry)
if !ok {
log.Tracef("cataloger failed to extract pdm lock metadata for package %+v", p.Name)
return dependency.Specification{}
}
// base package provides the package name without extras
provides := []string{p.Name}
// base requirements from Dependencies field
var requires []string
for _, dep := range meta.Dependencies {
depName := extractPackageName(dep)
if depName == "" {
continue
}
requires = append(requires, depName)
}
// create variants for each extras combination
var variants []dependency.ProvidesRequires
for _, extraVariant := range meta.Extras {
// each extra in the variant provides packagename[extra]
var variantProvides []string
for _, extra := range extraVariant.Extras {
variantProvides = append(variantProvides, packageRef(p.Name, extra))
}
// extract dependencies for this variant, excluding self-references
var variantRequires []string
for _, dep := range extraVariant.Dependencies {
depName := extractPackageName(dep)
if depName == "" || depName == p.Name {
// skip empty or self-references (e.g., coverage[toml] depends on coverage==7.4.1)
continue
}
variantRequires = append(variantRequires, depName)
}
if len(variantProvides) > 0 {
variants = append(variants, dependency.ProvidesRequires{
Provides: variantProvides,
Requires: variantRequires,
})
}
}
return dependency.Specification{
ProvidesRequires: dependency.ProvidesRequires{
Provides: provides,
Requires: requires,
},
Variants: variants,
}
}
func wheelEggDependencySpecifier(p pkg.Package) dependency.Specification { func wheelEggDependencySpecifier(p pkg.Package) dependency.Specification {
meta, ok := p.Metadata.(pkg.PythonPackage) meta, ok := p.Metadata.(pkg.PythonPackage)
if !ok { if !ok {
@ -115,8 +172,8 @@ func wheelEggDependencySpecifier(p pkg.Package) dependency.Specification {
} }
} }
// extractPackageName removes any extras, version constraints or environment markers from a given Requires-Dist field value (and // extractPackageName removes any extras, version constraints or environment markers from a dependency specifier string.
// semantically similar fields), leaving only the package name. // For example: "requests[security] >= 2.8.1 ; python_version < '3'" becomes "requests"
func extractPackageName(s string) string { func extractPackageName(s string) string {
// examples: // examples:
// requests [security,tests] --> requests // requests [security,tests] --> requests
@ -126,6 +183,8 @@ func extractPackageName(s string) string {
return strings.TrimSpace(internal.SplitAny(s, "[(<!=>~;")[0]) return strings.TrimSpace(internal.SplitAny(s, "[(<!=>~;")[0])
} }
// extractPackageNames applies extractPackageName to each string in the slice.
func extractPackageNames(ss []string) []string { func extractPackageNames(ss []string) []string {
var names []string var names []string
for _, s := range ss { for _, s := range ss {

View File

@ -275,3 +275,184 @@ func Test_poetryLockDependencySpecifier_againstPoetryLock(t *testing.T) {
}) })
} }
} }
func Test_pdmLockDependencySpecifier(t *testing.T) {
tests := []struct {
name string
p pkg.Package
want dependency.Specification
}{
{
name: "no dependencies",
p: pkg.Package{
Name: "foo",
Metadata: pkg.PythonPdmLockEntry{
Dependencies: []string{},
},
},
want: dependency.Specification{
ProvidesRequires: dependency.ProvidesRequires{
Provides: []string{"foo"},
},
},
},
{
name: "with simple dependencies",
p: pkg.Package{
Name: "requests",
Metadata: pkg.PythonPdmLockEntry{
Dependencies: []string{
"certifi>=2017.4.17",
"urllib3<1.27,>=1.21.1",
},
},
},
want: dependency.Specification{
ProvidesRequires: dependency.ProvidesRequires{
Provides: []string{"requests"},
Requires: []string{"certifi", "urllib3"},
},
},
},
{
name: "with dependencies containing environment markers",
p: pkg.Package{
Name: "requests",
Metadata: pkg.PythonPdmLockEntry{
Dependencies: []string{
"certifi>=2017.4.17",
"chardet<5,>=3.0.2; python_version < \"3\"",
"charset-normalizer~=2.0.0; python_version >= \"3\"",
"idna<3,>=2.5; python_version < \"3\"",
},
},
},
want: dependency.Specification{
ProvidesRequires: dependency.ProvidesRequires{
Provides: []string{"requests"},
Requires: []string{"certifi", "chardet", "charset-normalizer", "idna"},
},
},
},
{
name: "with dependencies containing extras",
p: pkg.Package{
Name: "pytest-cov",
Metadata: pkg.PythonPdmLockEntry{
Dependencies: []string{
"coverage[toml]>=5.2.1",
"pytest>=4.6",
},
},
},
want: dependency.Specification{
ProvidesRequires: dependency.ProvidesRequires{
Provides: []string{"pytest-cov"},
Requires: []string{"coverage", "pytest"},
},
},
},
{
name: "package with single extra variant",
p: pkg.Package{
Name: "coverage",
Metadata: pkg.PythonPdmLockEntry{
Dependencies: []string{}, // base package has no dependencies
Extras: []pkg.PythonPdmLockExtraVariant{
{
Extras: []string{"toml"},
Dependencies: []string{
"coverage==7.4.1", // self-reference, should be excluded
"tomli; python_full_version <= \"3.11.0a6\"",
},
},
},
},
},
want: dependency.Specification{
ProvidesRequires: dependency.ProvidesRequires{
Provides: []string{"coverage"},
Requires: nil,
},
Variants: []dependency.ProvidesRequires{
{
Provides: []string{"coverage[toml]"},
Requires: []string{"tomli"}, // coverage self-reference excluded
},
},
},
},
{
name: "package with multiple extras in one variant",
p: pkg.Package{
Name: "foo",
Metadata: pkg.PythonPdmLockEntry{
Dependencies: []string{"bar>=1.0"},
Extras: []pkg.PythonPdmLockExtraVariant{
{
Extras: []string{"dev", "test"},
Dependencies: []string{
"pytest>=6.0",
"black~=22.0",
"foo==1.0.0", // self-reference, should be excluded
},
},
},
},
},
want: dependency.Specification{
ProvidesRequires: dependency.ProvidesRequires{
Provides: []string{"foo"},
Requires: []string{"bar"},
},
Variants: []dependency.ProvidesRequires{
{
Provides: []string{"foo[dev]", "foo[test]"},
Requires: []string{"pytest", "black"}, // foo self-reference excluded
},
},
},
},
{
name: "package with multiple separate extra variants",
p: pkg.Package{
Name: "example",
Metadata: pkg.PythonPdmLockEntry{
Dependencies: []string{"requests"},
Extras: []pkg.PythonPdmLockExtraVariant{
{
Extras: []string{"redis"},
Dependencies: []string{"redis>=4.0"},
},
{
Extras: []string{"postgres"},
Dependencies: []string{"psycopg2>=2.9"},
},
},
},
},
want: dependency.Specification{
ProvidesRequires: dependency.ProvidesRequires{
Provides: []string{"example"},
Requires: []string{"requests"},
},
Variants: []dependency.ProvidesRequires{
{
Provides: []string{"example[redis]"},
Requires: []string{"redis"},
},
{
Provides: []string{"example[postgres]"},
Requires: []string{"psycopg2"},
},
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assert.Equal(t, tt.want, pdmLockDependencySpecifier(tt.p))
})
}
}

View File

@ -6,13 +6,13 @@ import (
"strings" "strings"
"github.com/BurntSushi/toml" "github.com/BurntSushi/toml"
"github.com/scylladb/go-set/strset"
"github.com/anchore/syft/internal/unknown" "github.com/anchore/syft/internal/unknown"
"github.com/anchore/syft/syft/artifact" "github.com/anchore/syft/syft/artifact"
"github.com/anchore/syft/syft/file" "github.com/anchore/syft/syft/file"
"github.com/anchore/syft/syft/pkg" "github.com/anchore/syft/syft/pkg"
"github.com/anchore/syft/syft/pkg/cataloger/generic" "github.com/anchore/syft/syft/pkg/cataloger/generic"
"github.com/anchore/syft/syft/pkg/cataloger/internal/dependency"
) )
type pdmLock struct { type pdmLock struct {
@ -30,7 +30,9 @@ type pdmLockPackage struct {
Version string `toml:"version"` Version string `toml:"version"`
RequiresPython string `toml:"requires_python"` RequiresPython string `toml:"requires_python"`
Summary string `toml:"summary"` Summary string `toml:"summary"`
Marker string `toml:"marker"`
Dependencies []string `toml:"dependencies"` Dependencies []string `toml:"dependencies"`
Extras []string `toml:"extras"`
Files []pdmLockPackageFile `toml:"files"` Files []pdmLockPackageFile `toml:"files"`
} }
@ -51,6 +53,117 @@ func newPdmLockParser(cfg CatalogerConfig) pdmLockParser {
} }
} }
// mergePdmLockPackages merges multiple package entries (with different extras) into a single PythonPdmLockEntry.
//
// PDM vs Poetry Lock File Behavior:
//
// PDM creates separate [[package]] entries in the lock file for each extras combination that is actually used
// in the dependency tree. For example, if your project depends on coverage[toml], PDM will create TWO entries:
// 1. A base "coverage" package entry (no extras field)
// 2. A "coverage" package entry with extras = ["toml"] and its own dependencies
//
// Poetry, in contrast, creates a SINGLE package entry per package and uses conditional markers to indicate
// when extra dependencies should be included.
//
// SBOM Representation:
//
// Semantically, "coverage" and "coverage[toml]" are NOT separate packages - they represent the same package
// with optional features enabled. The [toml] syntax is Python's way of requesting optional dependencies.
// Therefore, in the SBOM we create a SINGLE package node per name+version to accurately represent that:
//
// - There is one logical package (e.g., "coverage")
// - The package may be used with different feature sets (extras) by different dependents
// - For example: "pytest-cov" depends on "coverage[toml]" while another package might depend on base "coverage"
//
// This function consolidates PDM's multiple entries into:
// - Base package metadata (files, summary, dependencies without extras)
// - Extras variants (each combination of extras with its specific dependencies)
//
// This approach ensures dependency resolution works correctly: when a package requires "coverage[toml]",
// the dependency resolver can match it to the "coverage" package node and its "toml" variant.
func mergePdmLockPackages(packages []pdmLockPackage) pkg.PythonPdmLockEntry {
if len(packages) == 0 {
return pkg.PythonPdmLockEntry{}
}
var entry pkg.PythonPdmLockEntry
var baseFiles []pkg.PythonPdmFileEntry
// Separate base package from extras variants
// note: this logic processes packages in order and assumes the base package (no extras) appears
// before extras variants in the PDM lock file, which is PDM's current behavior
for _, p := range packages {
// Convert files format
var files []pkg.PythonPdmFileEntry
for _, f := range p.Files {
// skip files with invalid hash format (missing colon separator between algorithm and value)
if colonIndex := strings.Index(f.Hash, ":"); colonIndex != -1 {
algorithm := f.Hash[:colonIndex]
value := f.Hash[colonIndex+1:]
files = append(files, pkg.PythonPdmFileEntry{
URL: f.File,
Digest: pkg.PythonFileDigest{
Algorithm: algorithm,
Value: value,
},
})
}
}
// Base package (no extras field or empty extras)
if len(p.Extras) == 0 {
entry.Summary = p.Summary
entry.RequiresPython = p.RequiresPython
entry.Dependencies = p.Dependencies
entry.Marker = p.Marker
baseFiles = files
} else {
// Extras variant
variant := pkg.PythonPdmLockExtraVariant{
Extras: p.Extras,
Dependencies: p.Dependencies,
Marker: p.Marker,
}
// Only include files if different from base
// For now, we'll compare lengths as a simple check
if len(baseFiles) == 0 || !filesEqual(baseFiles, files) {
variant.Files = files
}
entry.Extras = append(entry.Extras, variant)
}
}
// Store base files
entry.Files = baseFiles
// If no base package was found but we have extras, use first package's metadata as base
if entry.Summary == "" && len(packages) > 0 {
entry.Summary = packages[0].Summary
entry.RequiresPython = packages[0].RequiresPython
entry.Dependencies = packages[0].Dependencies
entry.Marker = packages[0].Marker
}
return entry
}
// filesEqual checks if two file slices are equal by comparing URL and digest fields.
// assumes files appear in the same order in both slices.
func filesEqual(a, b []pkg.PythonPdmFileEntry) bool {
if len(a) != len(b) {
return false
}
for i := range a {
if a[i].URL != b[i].URL || a[i].Digest.Algorithm != b[i].Digest.Algorithm || a[i].Digest.Value != b[i].Digest.Value {
return false
}
}
return true
}
// parsePdmLock is a parser function for pdm.lock contents, returning python packages discovered. // parsePdmLock is a parser function for pdm.lock contents, returning python packages discovered.
func (plp pdmLockParser) parsePdmLock(ctx context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) { func (plp pdmLockParser) parsePdmLock(ctx context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
var lock pdmLock var lock pdmLock
@ -59,94 +172,38 @@ func (plp pdmLockParser) parsePdmLock(ctx context.Context, _ file.Resolver, _ *g
return nil, nil, fmt.Errorf("failed to parse pdm.lock file: %w", err) return nil, nil, fmt.Errorf("failed to parse pdm.lock file: %w", err)
} }
var pkgs []pkg.Package // Group packages by name@version since PDM creates separate entries for different extras combinations
packageGroups := make(map[string][]pdmLockPackage)
for _, p := range lock.Package { for _, p := range lock.Package {
var files []pkg.PythonFileRecord key := p.Name + "@" + p.Version
for _, f := range p.Files { packageGroups[key] = append(packageGroups[key], p)
if colonIndex := strings.Index(f.Hash, ":"); colonIndex != -1 { }
algorithm := f.Hash[:colonIndex]
value := f.Hash[colonIndex+1:]
files = append(files, pkg.PythonFileRecord{ // Merge package groups and create packages
Path: f.File, var pkgs []pkg.Package
Digest: &pkg.PythonFileDigest{ for _, group := range packageGroups {
Algorithm: algorithm, if len(group) == 0 {
Value: value, continue
},
})
}
} }
// only store used part of the dependency information // Use first package for name/version (same across all entries in group)
var deps []string name := group[0].Name
for _, dep := range p.Dependencies { version := group[0].Version
// remove environment markers (after semicolon)
dep = strings.Split(dep, ";")[0]
dep = strings.TrimSpace(dep)
if dep != "" {
deps = append(deps, dep)
}
}
pythonPkgMetadata := pkg.PythonPdmLockEntry{ // Merge all entries into single metadata
Files: files, pythonPkgMetadata := mergePdmLockPackages(group)
Summary: p.Summary,
Dependencies: deps,
}
pkgs = append(pkgs, newPackageForIndexWithMetadata( pkgs = append(pkgs, newPackageForIndexWithMetadata(
ctx, ctx,
plp.licenseResolver, plp.licenseResolver,
p.Name, name,
p.Version, version,
pythonPkgMetadata, pythonPkgMetadata,
reader.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), reader.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation),
)) ))
} }
relationships := buildPdmRelationships(pkgs) relationships := dependency.Resolve(pdmLockDependencySpecifier, pkgs)
return pkgs, relationships, unknown.IfEmptyf(pkgs, "unable to determine packages") return pkgs, relationships, unknown.IfEmptyf(pkgs, "unable to determine packages")
} }
func buildPdmRelationships(pkgs []pkg.Package) []artifact.Relationship {
pkgMap := make(map[string]pkg.Package, len(pkgs))
for _, p := range pkgs {
pkgMap[p.Name] = p
}
var relationships []artifact.Relationship
for _, p := range pkgs {
meta, ok := p.Metadata.(pkg.PythonPdmLockEntry)
if !ok {
continue
}
// collect unique dependencies
added := strset.New()
for _, depName := range meta.Dependencies {
// Handle version specifiers
depName = strings.Split(depName, "<")[0]
depName = strings.Split(depName, ">")[0]
depName = strings.Split(depName, "=")[0]
depName = strings.Split(depName, "~")[0]
depName = strings.TrimSpace(depName)
if depName == "" || added.Has(depName) {
continue
}
added.Add(depName)
if dep, exists := pkgMap[depName]; exists {
relationships = append(relationships, artifact.Relationship{
From: dep,
To: p,
Type: artifact.DependencyOfRelationship,
})
}
}
}
return relationships
}

View File

@ -2,8 +2,12 @@ package python
import ( import (
"context" "context"
"os"
"testing" "testing"
"github.com/google/go-cmp/cmp"
"github.com/stretchr/testify/require"
"github.com/anchore/syft/syft/artifact" "github.com/anchore/syft/syft/artifact"
"github.com/anchore/syft/syft/file" "github.com/anchore/syft/syft/file"
"github.com/anchore/syft/syft/pkg" "github.com/anchore/syft/syft/pkg"
@ -24,22 +28,24 @@ func TestParsePdmLock(t *testing.T) {
Type: pkg.PythonPkg, Type: pkg.PythonPkg,
Metadata: pkg.PythonPdmLockEntry{ Metadata: pkg.PythonPdmLockEntry{
Summary: "Python package for providing Mozilla's CA Bundle.", Summary: "Python package for providing Mozilla's CA Bundle.",
Files: []pkg.PythonFileRecord{ Marker: `python_version >= "3.6"`,
Files: []pkg.PythonPdmFileEntry{
{ {
Path: "", URL: "",
Digest: &pkg.PythonFileDigest{ Digest: pkg.PythonFileDigest{
Algorithm: "sha256", Algorithm: "sha256",
Value: "3d5da6925056f6f18f119200434a4780a94263f10d1c21d032a6f6b2baa20651", Value: "3d5da6925056f6f18f119200434a4780a94263f10d1c21d032a6f6b2baa20651",
}, },
}, },
{ {
Path: "", URL: "",
Digest: &pkg.PythonFileDigest{ Digest: pkg.PythonFileDigest{
Algorithm: "sha256", Algorithm: "sha256",
Value: "ca78db4565a652026a4db2bcdf68f2fb589ea80d0be70e03929ed730746b84fe", Value: "ca78db4565a652026a4db2bcdf68f2fb589ea80d0be70e03929ed730746b84fe",
}, },
}, },
}, },
RequiresPython: ">=3.6",
}, },
}, },
{ {
@ -51,17 +57,18 @@ func TestParsePdmLock(t *testing.T) {
Type: pkg.PythonPkg, Type: pkg.PythonPkg,
Metadata: pkg.PythonPdmLockEntry{ Metadata: pkg.PythonPdmLockEntry{
Summary: "Universal encoding detector for Python 2 and 3", Summary: "Universal encoding detector for Python 2 and 3",
Files: []pkg.PythonFileRecord{ Marker: `os_name == "nt"`,
Files: []pkg.PythonPdmFileEntry{
{ {
Path: "", URL: "",
Digest: &pkg.PythonFileDigest{ Digest: pkg.PythonFileDigest{
Algorithm: "sha256", Algorithm: "sha256",
Value: "fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691", Value: "fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691",
}, },
}, },
{ {
Path: "", URL: "",
Digest: &pkg.PythonFileDigest{ Digest: pkg.PythonFileDigest{
Algorithm: "sha256", Algorithm: "sha256",
Value: "84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae", Value: "84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae",
}, },
@ -78,22 +85,24 @@ func TestParsePdmLock(t *testing.T) {
Type: pkg.PythonPkg, Type: pkg.PythonPkg,
Metadata: pkg.PythonPdmLockEntry{ Metadata: pkg.PythonPdmLockEntry{
Summary: "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet.", Summary: "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet.",
Files: []pkg.PythonFileRecord{ Marker: `python_version >= "3.6"`,
Files: []pkg.PythonPdmFileEntry{
{ {
Path: "", URL: "",
Digest: &pkg.PythonFileDigest{ Digest: pkg.PythonFileDigest{
Algorithm: "sha256", Algorithm: "sha256",
Value: "6881edbebdb17b39b4eaaa821b438bf6eddffb4468cf344f09f89def34a8b1df", Value: "6881edbebdb17b39b4eaaa821b438bf6eddffb4468cf344f09f89def34a8b1df",
}, },
}, },
{ {
Path: "", URL: "",
Digest: &pkg.PythonFileDigest{ Digest: pkg.PythonFileDigest{
Algorithm: "sha256", Algorithm: "sha256",
Value: "2857e29ff0d34db842cd7ca3230549d1a697f96ee6d3fb071cfa6c7393832597", Value: "2857e29ff0d34db842cd7ca3230549d1a697f96ee6d3fb071cfa6c7393832597",
}, },
}, },
}, },
RequiresPython: ">=3.5.0",
}, },
}, },
{ {
@ -105,17 +114,18 @@ func TestParsePdmLock(t *testing.T) {
Type: pkg.PythonPkg, Type: pkg.PythonPkg,
Metadata: pkg.PythonPdmLockEntry{ Metadata: pkg.PythonPdmLockEntry{
Summary: "Cross-platform colored terminal text.", Summary: "Cross-platform colored terminal text.",
Files: []pkg.PythonFileRecord{ Marker: `sys_platform == "win32"`,
Files: []pkg.PythonPdmFileEntry{
{ {
Path: "", URL: "",
Digest: &pkg.PythonFileDigest{ Digest: pkg.PythonFileDigest{
Algorithm: "sha256", Algorithm: "sha256",
Value: "463f8483208e921368c9f306094eb6f725c6ca42b0f97e313cb5d5512459feda", Value: "463f8483208e921368c9f306094eb6f725c6ca42b0f97e313cb5d5512459feda",
}, },
}, },
{ {
Path: "", URL: "",
Digest: &pkg.PythonFileDigest{ Digest: pkg.PythonFileDigest{
Algorithm: "sha256", Algorithm: "sha256",
Value: "48eb22f4f8461b1df5734a074b57042430fb06e1d61bd1e11b078c0fe6d7a1f1", Value: "48eb22f4f8461b1df5734a074b57042430fb06e1d61bd1e11b078c0fe6d7a1f1",
}, },
@ -132,17 +142,17 @@ func TestParsePdmLock(t *testing.T) {
Type: pkg.PythonPkg, Type: pkg.PythonPkg,
Metadata: pkg.PythonPdmLockEntry{ Metadata: pkg.PythonPdmLockEntry{
Summary: "Internationalized Domain Names in Applications (IDNA)", Summary: "Internationalized Domain Names in Applications (IDNA)",
Files: []pkg.PythonFileRecord{ Files: []pkg.PythonPdmFileEntry{
{ {
Path: "", URL: "",
Digest: &pkg.PythonFileDigest{ Digest: pkg.PythonFileDigest{
Algorithm: "sha256", Algorithm: "sha256",
Value: "156a6814fb5ac1fc6850fb002e0852d56c0c8d2531923a51032d1b70760e186e", Value: "156a6814fb5ac1fc6850fb002e0852d56c0c8d2531923a51032d1b70760e186e",
}, },
}, },
{ {
Path: "", URL: "",
Digest: &pkg.PythonFileDigest{ Digest: pkg.PythonFileDigest{
Algorithm: "sha256", Algorithm: "sha256",
Value: "684a38a6f903c1d71d6d5fac066b58d7768af4de2b832e426ec79c30daa94a16", Value: "684a38a6f903c1d71d6d5fac066b58d7768af4de2b832e426ec79c30daa94a16",
}, },
@ -159,17 +169,17 @@ func TestParsePdmLock(t *testing.T) {
Type: pkg.PythonPkg, Type: pkg.PythonPkg,
Metadata: pkg.PythonPdmLockEntry{ Metadata: pkg.PythonPdmLockEntry{
Summary: "library with cross-python path, ini-parsing, io, code, log facilities", Summary: "library with cross-python path, ini-parsing, io, code, log facilities",
Files: []pkg.PythonFileRecord{ Files: []pkg.PythonPdmFileEntry{
{ {
Path: "", URL: "",
Digest: &pkg.PythonFileDigest{ Digest: pkg.PythonFileDigest{
Algorithm: "sha256", Algorithm: "sha256",
Value: "2ccb79b01769d99115aa600d7eed99f524bf752bba8f041dc1c184853514655a", Value: "2ccb79b01769d99115aa600d7eed99f524bf752bba8f041dc1c184853514655a",
}, },
}, },
{ {
Path: "", URL: "",
Digest: &pkg.PythonFileDigest{ Digest: pkg.PythonFileDigest{
Algorithm: "sha256", Algorithm: "sha256",
Value: "0f2d585d22050e90c7d293b6451c83db097df77871974d90efd5a30dc12fcde3", Value: "0f2d585d22050e90c7d293b6451c83db097df77871974d90efd5a30dc12fcde3",
}, },
@ -186,26 +196,26 @@ func TestParsePdmLock(t *testing.T) {
Type: pkg.PythonPkg, Type: pkg.PythonPkg,
Metadata: pkg.PythonPdmLockEntry{ Metadata: pkg.PythonPdmLockEntry{
Summary: "pytest: simple powerful testing with Python", Summary: "pytest: simple powerful testing with Python",
Files: []pkg.PythonFileRecord{ Files: []pkg.PythonPdmFileEntry{
{ {
Path: "", URL: "",
Digest: &pkg.PythonFileDigest{ Digest: pkg.PythonFileDigest{
Algorithm: "sha256", Algorithm: "sha256",
Value: "6d5bd4f7113b444c55a3bbb5c738a3dd80d43563d063fc42dcb0aaefbdd78b81", Value: "6d5bd4f7113b444c55a3bbb5c738a3dd80d43563d063fc42dcb0aaefbdd78b81",
}, },
}, },
{ {
Path: "", URL: "",
Digest: &pkg.PythonFileDigest{ Digest: pkg.PythonFileDigest{
Algorithm: "sha256", Algorithm: "sha256",
Value: "241d7e7798d79192a123ceaf64c602b4d233eacf6d6e42ae27caa97f498b7dc6", Value: "241d7e7798d79192a123ceaf64c602b4d233eacf6d6e42ae27caa97f498b7dc6",
}, },
}, },
}, },
Dependencies: []string{ Dependencies: []string{
"argparse", `argparse; python_version == "2.6"`,
"colorama", `colorama; sys_platform == "win32"`,
"ordereddict", `ordereddict; python_version == "2.6"`,
"py>=1.4.33", "py>=1.4.33",
"setuptools", "setuptools",
}, },
@ -220,28 +230,30 @@ func TestParsePdmLock(t *testing.T) {
Type: pkg.PythonPkg, Type: pkg.PythonPkg,
Metadata: pkg.PythonPdmLockEntry{ Metadata: pkg.PythonPdmLockEntry{
Summary: "Python HTTP for Humans.", Summary: "Python HTTP for Humans.",
Files: []pkg.PythonFileRecord{ Marker: `python_version >= "3.6"`,
Files: []pkg.PythonPdmFileEntry{
{ {
Path: "", URL: "",
Digest: &pkg.PythonFileDigest{ Digest: pkg.PythonFileDigest{
Algorithm: "sha256", Algorithm: "sha256",
Value: "f22fa1e554c9ddfd16e6e41ac79759e17be9e492b3587efa038054674760e72d", Value: "f22fa1e554c9ddfd16e6e41ac79759e17be9e492b3587efa038054674760e72d",
}, },
}, },
{ {
Path: "", URL: "",
Digest: &pkg.PythonFileDigest{ Digest: pkg.PythonFileDigest{
Algorithm: "sha256", Algorithm: "sha256",
Value: "68d7c56fd5a8999887728ef304a6d12edc7be74f1cfa47714fc8b414525c9a61", Value: "68d7c56fd5a8999887728ef304a6d12edc7be74f1cfa47714fc8b414525c9a61",
}, },
}, },
}, },
RequiresPython: ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*",
Dependencies: []string{ Dependencies: []string{
"certifi>=2017.4.17", "certifi>=2017.4.17",
"chardet<5,>=3.0.2", `chardet<5,>=3.0.2; python_version < "3"`,
"charset-normalizer~=2.0.0", `charset-normalizer~=2.0.0; python_version >= "3"`,
"idna<3,>=2.5", `idna<3,>=2.5; python_version < "3"`,
"idna<4,>=2.5", `idna<4,>=2.5; python_version >= "3"`,
"urllib3<1.27,>=1.21.1", "urllib3<1.27,>=1.21.1",
}, },
}, },
@ -255,22 +267,23 @@ func TestParsePdmLock(t *testing.T) {
Type: pkg.PythonPkg, Type: pkg.PythonPkg,
Metadata: pkg.PythonPdmLockEntry{ Metadata: pkg.PythonPdmLockEntry{
Summary: "Easily download, build, install, upgrade, and uninstall Python packages", Summary: "Easily download, build, install, upgrade, and uninstall Python packages",
Files: []pkg.PythonFileRecord{ Files: []pkg.PythonPdmFileEntry{
{ {
Path: "", URL: "",
Digest: &pkg.PythonFileDigest{ Digest: pkg.PythonFileDigest{
Algorithm: "sha256", Algorithm: "sha256",
Value: "f7cddbb5f5c640311eb00eab6e849f7701fa70bf6a183fc8a2c33dd1d1672fb2", Value: "f7cddbb5f5c640311eb00eab6e849f7701fa70bf6a183fc8a2c33dd1d1672fb2",
}, },
}, },
{ {
Path: "", URL: "",
Digest: &pkg.PythonFileDigest{ Digest: pkg.PythonFileDigest{
Algorithm: "sha256", Algorithm: "sha256",
Value: "8fca9275c89964f13da985c3656cb00ba029d7f3916b37990927ffdf264e7926", Value: "8fca9275c89964f13da985c3656cb00ba029d7f3916b37990927ffdf264e7926",
}, },
}, },
}, },
RequiresPython: ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*",
}, },
}, },
{ {
@ -282,22 +295,24 @@ func TestParsePdmLock(t *testing.T) {
Type: pkg.PythonPkg, Type: pkg.PythonPkg,
Metadata: pkg.PythonPdmLockEntry{ Metadata: pkg.PythonPdmLockEntry{
Summary: "HTTP library with thread-safe connection pooling, file post, and more.", Summary: "HTTP library with thread-safe connection pooling, file post, and more.",
Files: []pkg.PythonFileRecord{ Marker: `python_version >= "3.6"`,
Files: []pkg.PythonPdmFileEntry{
{ {
Path: "", URL: "",
Digest: &pkg.PythonFileDigest{ Digest: pkg.PythonFileDigest{
Algorithm: "sha256", Algorithm: "sha256",
Value: "0ed14ccfbf1c30a9072c7ca157e4319b70d65f623e91e7b32fadb2853431016e", Value: "0ed14ccfbf1c30a9072c7ca157e4319b70d65f623e91e7b32fadb2853431016e",
}, },
}, },
{ {
Path: "", URL: "",
Digest: &pkg.PythonFileDigest{ Digest: pkg.PythonFileDigest{
Algorithm: "sha256", Algorithm: "sha256",
Value: "40c2dc0c681e47eb8f90e7e27bf6ff7df2e677421fd46756da1161c39ca70d32", Value: "40c2dc0c681e47eb8f90e7e27bf6ff7df2e677421fd46756da1161c39ca70d32",
}, },
}, },
}, },
RequiresPython: "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7",
}, },
}, },
} }
@ -390,22 +405,24 @@ func TestParsePdmLockWithLicenseEnrichment(t *testing.T) {
Type: pkg.PythonPkg, Type: pkg.PythonPkg,
Metadata: pkg.PythonPdmLockEntry{ Metadata: pkg.PythonPdmLockEntry{
Summary: "Python package for providing Mozilla's CA Bundle.", Summary: "Python package for providing Mozilla's CA Bundle.",
Files: []pkg.PythonFileRecord{ Marker: `python_version >= "3.7"`,
Files: []pkg.PythonPdmFileEntry{
{ {
Path: "", URL: "",
Digest: &pkg.PythonFileDigest{ Digest: pkg.PythonFileDigest{
Algorithm: "sha256", Algorithm: "sha256",
Value: "47c09d31ccf2acf0be3f701ea53595ee7e0b8fa08801c6624be771df09ae7b43", Value: "47c09d31ccf2acf0be3f701ea53595ee7e0b8fa08801c6624be771df09ae7b43",
}, },
}, },
{ {
Path: "", URL: "",
Digest: &pkg.PythonFileDigest{ Digest: pkg.PythonFileDigest{
Algorithm: "sha256", Algorithm: "sha256",
Value: "0f212c2744a9bb6de0c56639a6f68afe01ecd92d91f14ae897c4fe7bbeeef0de", Value: "0f212c2744a9bb6de0c56639a6f68afe01ecd92d91f14ae897c4fe7bbeeef0de",
}, },
}, },
}, },
RequiresPython: ">=3.7",
}, },
}, },
}, },
@ -424,10 +441,263 @@ func TestParsePdmLockWithLicenseEnrichment(t *testing.T) {
} }
} }
func Test_corruptPdmLock(t *testing.T) { func TestParsePdmLockWithExtras(t *testing.T) {
// This test verifies that PDM's multiple package entries for different extras combinations
// are correctly merged into a single package node in the SBOM.
//
// The fixture contains TWO [[package]] entries for "coverage":
// 1. Base coverage package (no extras)
// 2. coverage with extras = ["toml"]
//
// We should get exactly ONE coverage package in the output, with extras properly tracked.
fixture := "test-fixtures/pdm-lock-extras/pdm.lock"
pdmLockParser := newPdmLockParser(DefaultCatalogerConfig()) pdmLockParser := newPdmLockParser(DefaultCatalogerConfig())
fh, err := os.Open(fixture)
require.NoError(t, err)
defer fh.Close()
pkgs, relationships, err := pdmLockParser.parsePdmLock(
context.TODO(),
nil,
nil,
file.NewLocationReadCloser(file.NewLocation(fixture), fh),
)
require.NoError(t, err)
// Verify we have the expected number of packages (NOT duplicated coverage)
require.Len(t, pkgs, 5, "should have exactly 5 packages: coverage, pytest, pytest-cov, tomli, uvloop")
// Find the coverage package and verify it's only present once
var coveragePkg *pkg.Package
coverageCount := 0
for i := range pkgs {
if pkgs[i].Name == "coverage" {
coverageCount++
coveragePkg = &pkgs[i]
}
}
require.Equal(t, 1, coverageCount, "coverage should appear exactly ONCE in the package list (PDM has it twice in the lock file)")
require.NotNil(t, coveragePkg, "coverage package should be found")
// This test verifies file deduplication behavior!
// The fixture has identical files in both base and extras=["toml"] entries.
// After merging, the base should have Files populated, but the extras variant should NOT
// have Files (they're deduplicated because they're identical to base).
coverageMeta, ok := coveragePkg.Metadata.(pkg.PythonPdmLockEntry)
require.True(t, ok, "coverage metadata should be PythonPdmLockEntry")
expectedMeta := pkg.PythonPdmLockEntry{
Summary: "Code coverage measurement for Python",
RequiresPython: ">=3.8",
Files: []pkg.PythonPdmFileEntry{
{
URL: "coverage-7.4.1-cp310-cp310-macosx_10_9_x86_64.whl",
Digest: pkg.PythonFileDigest{
Algorithm: "sha256",
Value: "077d366e724f24fc02dbfe9d946534357fda71af9764ff99d73c3c596001bbd7",
},
},
{
URL: "coverage-7.4.1.tar.gz",
Digest: pkg.PythonFileDigest{
Algorithm: "sha256",
Value: "1ed4b95480952b1a26d863e546fa5094564aa0065e1e5f0d4d0041f293251d04",
},
},
},
Extras: []pkg.PythonPdmLockExtraVariant{
{
Extras: []string{"toml"},
Dependencies: []string{
"coverage==7.4.1",
"tomli; python_full_version <= \"3.11.0a6\"",
},
// Files is nil/empty here because they're identical to base (deduplicated)
},
},
}
if diff := cmp.Diff(expectedMeta, coverageMeta); diff != "" {
t.Errorf("coverage metadata mismatch (-want +got):\n%s", diff)
}
// Verify relationships were created
require.NotEmpty(t, relationships, "relationships should be created")
// Verify pytest-cov has a relationship to coverage
// Build a package map for easy lookup
pkgMap := make(map[string]pkg.Package)
for _, p := range pkgs {
pkgMap[p.Name] = p
}
// Verify tomli package has marker preserved
var tomliPkg *pkg.Package
for i := range pkgs {
if pkgs[i].Name == "tomli" {
tomliPkg = &pkgs[i]
break
}
}
require.NotNil(t, tomliPkg, "tomli package should be found")
tomliMeta, ok := tomliPkg.Metadata.(pkg.PythonPdmLockEntry)
require.True(t, ok, "tomli metadata should be PythonPdmLockEntry")
require.Equal(t, `python_version < "3.11"`, tomliMeta.Marker, "tomli should have marker preserved")
// Verify uvloop package has complex marker preserved (multiple AND conditions, negations, mixed quotes)
var uvloopPkg *pkg.Package
for i := range pkgs {
if pkgs[i].Name == "uvloop" {
uvloopPkg = &pkgs[i]
break
}
}
require.NotNil(t, uvloopPkg, "uvloop package should be found")
uvloopMeta, ok := uvloopPkg.Metadata.(pkg.PythonPdmLockEntry)
require.True(t, ok, "uvloop metadata should be PythonPdmLockEntry")
require.Equal(t, `platform_python_implementation != 'PyPy' and sys_platform != 'win32' and python_version >= "3.8"`, uvloopMeta.Marker, "uvloop should have complex marker preserved exactly as-is")
var foundPytestCovToCoverage bool
for _, rel := range relationships {
toPkg, toOk := rel.To.(pkg.Package)
fromPkg, fromOk := rel.From.(pkg.Package)
if toOk && fromOk && toPkg.Name == "pytest-cov" && fromPkg.Name == "coverage" {
foundPytestCovToCoverage = true
break
}
}
require.True(t, foundPytestCovToCoverage, "should have a dependency relationship from coverage to pytest-cov")
}
func TestParsePdmLockWithSeparateFilesFixture(t *testing.T) {
// verify that PythonPdmLockExtraVariant metadata is properly populated when parsing PDM lock files
// with extras variants. The separate-files fixture contains rfc3986 with base + extras=["idna2008"] variant.
//
// The fixture contains TWO [[package]] entries for "rfc3986":
// 1. Base rfc3986 package (no extras, no dependencies)
// 2. rfc3986 with extras = ["idna2008"] and dependencies = ["idna", "rfc3986==1.5.0"]
//
// We should get exactly ONE rfc3986 package in the output, with the extras variant properly tracked
// in the Extras field.
fixture := "test-fixtures/pdm-lock-separate-files/pdm.lock"
pdmLockParser := newPdmLockParser(DefaultCatalogerConfig())
fh, err := os.Open(fixture)
require.NoError(t, err)
defer fh.Close()
pkgs, relationships, err := pdmLockParser.parsePdmLock(
context.TODO(),
nil,
nil,
file.NewLocationReadCloser(file.NewLocation(fixture), fh),
)
require.NoError(t, err)
// Find the rfc3986 package and verify it's only present once
var rfc3986Pkg *pkg.Package
rfc3986Count := 0
for i := range pkgs {
if pkgs[i].Name == "rfc3986" {
rfc3986Count++
rfc3986Pkg = &pkgs[i]
}
}
require.Equal(t, 1, rfc3986Count)
require.NotNil(t, rfc3986Pkg)
require.Equal(t, "rfc3986", rfc3986Pkg.Name)
require.Equal(t, "1.5.0", rfc3986Pkg.Version)
rfc3986Meta, ok := rfc3986Pkg.Metadata.(pkg.PythonPdmLockEntry)
require.True(t, ok)
expectedMeta := pkg.PythonPdmLockEntry{
Summary: "Validating URI References per RFC 3986",
RequiresPython: "",
Files: nil, // base package has no files in fixture
Extras: []pkg.PythonPdmLockExtraVariant{
{
Extras: []string{"idna2008"},
Dependencies: []string{
"idna",
"rfc3986==1.5.0",
},
Files: nil, // variant also has no files (fixture has no files for either entry)
},
},
}
if diff := cmp.Diff(expectedMeta, rfc3986Meta); diff != "" {
t.Errorf("rfc3986 metadata mismatch (-want +got):\n%s", diff)
}
require.NotEmpty(t, relationships, "relationships should be created")
}
func TestMergePdmLockPackagesNoBasePackage(t *testing.T) {
// test the edge case where only extras variants exist (no base package entry)
// this can happen if PDM lock file only contains package entries with extras
packages := []pdmLockPackage{
{
Name: "test-package",
Version: "1.0.0",
RequiresPython: ">=3.8",
Summary: "Test package summary",
Marker: "extra == 'dev'",
Dependencies: []string{"pytest", "test-package==1.0.0"},
Extras: []string{"dev"},
Files: []pdmLockPackageFile{
{
File: "test-package-1.0.0.tar.gz",
Hash: "sha256:abc123",
},
},
},
{
Name: "test-package",
Version: "1.0.0",
RequiresPython: ">=3.8",
Summary: "Test package summary",
Marker: "extra == 'test'",
Dependencies: []string{"coverage", "test-package==1.0.0"},
Extras: []string{"test"},
Files: []pdmLockPackageFile{
{
File: "test-package-1.0.0.tar.gz",
Hash: "sha256:abc123",
},
},
},
}
entry := mergePdmLockPackages(packages)
// verify fallback logic: when no base package exists, first package's metadata is used
require.Equal(t, "Test package summary", entry.Summary)
require.Equal(t, ">=3.8", entry.RequiresPython)
require.Equal(t, []string{"pytest", "test-package==1.0.0"}, entry.Dependencies)
require.Equal(t, "extra == 'dev'", entry.Marker)
// verify both extras variants are present
require.Len(t, entry.Extras, 2)
require.Equal(t, []string{"dev"}, entry.Extras[0].Extras)
require.Equal(t, []string{"pytest", "test-package==1.0.0"}, entry.Extras[0].Dependencies)
require.Equal(t, []string{"test"}, entry.Extras[1].Extras)
require.Equal(t, []string{"coverage", "test-package==1.0.0"}, entry.Extras[1].Dependencies)
}
func Test_corruptPdmLock(t *testing.T) {
psr := newPdmLockParser(DefaultCatalogerConfig())
pkgtest.NewCatalogTester(). pkgtest.NewCatalogTester().
FromFile(t, "test-fixtures/glob-paths/src/pdm.lock"). FromFile(t, "test-fixtures/glob-paths/src/pdm.lock").
WithError(). WithError().
TestParser(t, pdmLockParser.parsePdmLock) TestParser(t, psr.parsePdmLock)
} }

View File

@ -0,0 +1,88 @@
# This file is @generated by PDM.
# It is not intended for manual editing.
[metadata]
groups = ["default", "dev"]
strategy = ["cross_platform", "inherit_metadata"]
lock_version = "4.4.1"
content_hash = "sha256:d14b90a22c7fff00910b4f916106bee51a11f0d0cd3c7f588aef0b1ee01d3efa"
[[package]]
name = "coverage"
version = "7.4.1"
requires_python = ">=3.8"
summary = "Code coverage measurement for Python"
groups = ["dev"]
files = [
{file = "coverage-7.4.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:077d366e724f24fc02dbfe9d946534357fda71af9764ff99d73c3c596001bbd7"},
{file = "coverage-7.4.1.tar.gz", hash = "sha256:1ed4b95480952b1a26d863e546fa5094564aa0065e1e5f0d4d0041f293251d04"},
]
[[package]]
name = "coverage"
version = "7.4.1"
# IMPORTANT! PDM creates a separate entry for this extras combination
extras = ["toml"]
requires_python = ">=3.8"
summary = "Code coverage measurement for Python"
groups = ["dev"]
dependencies = [
"coverage==7.4.1",
"tomli; python_full_version <= \"3.11.0a6\"",
]
files = [
{file = "coverage-7.4.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:077d366e724f24fc02dbfe9d946534357fda71af9764ff99d73c3c596001bbd7"},
{file = "coverage-7.4.1.tar.gz", hash = "sha256:1ed4b95480952b1a26d863e546fa5094564aa0065e1e5f0d4d0041f293251d04"},
]
[[package]]
name = "pytest"
version = "8.0.1"
requires_python = ">=3.8"
summary = "pytest: simple powerful testing with Python"
groups = ["dev"]
files = [
{file = "pytest-8.0.1-py3-none-any.whl", hash = "sha256:3e4f16fe1c0a9dc9d9389161c127c3edc5d810c38d6793042fb81d9f48a59fca"},
{file = "pytest-8.0.1.tar.gz", hash = "sha256:267f6563751877d772019b13aacbe4e860d73fe8f651f28112e9ac37de7513ae"},
]
[[package]]
name = "pytest-cov"
version = "4.1.0"
requires_python = ">=3.7"
summary = "Pytest plugin for measuring coverage."
groups = ["dev"]
# IMPORTANT! This package depends on coverage with the 'toml' extra
dependencies = [
"coverage[toml]>=5.2.1",
"pytest>=4.6",
]
files = [
{file = "pytest-cov-4.1.0.tar.gz", hash = "sha256:3904b13dfbfec47f003b8e77fd5b589cd11904a21ddf1ab38a64f204d6a10ef6"},
{file = "pytest_cov-4.1.0-py3-none-any.whl", hash = "sha256:6ba70b9e97e69fcc3fb45bfeab2d0a138fb65c4d0d6a41ef33983ad114be8c3a"},
]
[[package]]
name = "tomli"
version = "2.0.1"
requires_python = ">=3.7"
summary = "A lil' TOML parser"
groups = ["dev"]
marker = "python_version < \"3.11\""
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 = "uvloop"
version = "0.19.0"
requires_python = ">=3.8"
summary = "Fast implementation of asyncio event loop"
groups = ["dev"]
# IMPORTANT! This package has a complex marker with multiple AND conditions, negations, and mixed quote styles
marker = "platform_python_implementation != 'PyPy' and sys_platform != 'win32' and python_version >= \"3.8\""
files = [
{file = "uvloop-0.19.0.tar.gz", hash = "sha256:0246f4fd1bf2bf702e06b0d45ee91677ee5c31242f39aab4ea6fe0c51aedd0fd"},
{file = "uvloop-0.19.0-cp38-cp38-manylinux_2_17_x86_64.whl", hash = "sha256:de4313d7f575474c8f5a12e163f6d89c0a878bc49219641d49e6f1444369a90e"},
]

View File

@ -0,0 +1,957 @@
[[package]]
name = "anyio"
version = "3.6.1"
requires_python = ">=3.6.2"
summary = "High level compatibility layer for multiple asynchronous event loop implementations"
dependencies = [
"idna>=2.8",
"sniffio>=1.1",
]
[[package]]
name = "appnope"
version = "0.1.3"
summary = "Disable App Nap on macOS >= 10.9"
[[package]]
name = "asttokens"
version = "2.0.8"
summary = "Annotate AST trees with source code positions"
dependencies = [
"six",
]
[[package]]
name = "backcall"
version = "0.2.0"
summary = "Specifications for callback functions passed in to an API"
[[package]]
name = "black"
version = "22.6.0"
requires_python = ">=3.6.2"
summary = "The uncompromising code formatter."
dependencies = [
"click>=8.0.0",
"mypy-extensions>=0.4.3",
"pathspec>=0.9.0",
"platformdirs>=2",
"tomli>=1.1.0; python_full_version < \"3.11.0a7\"",
]
[[package]]
name = "certifi"
version = "2022.6.15"
requires_python = ">=3.6"
summary = "Python package for providing Mozilla's CA Bundle."
[[package]]
name = "cffi"
version = "1.15.1"
summary = "Foreign Function Interface for Python calling C code."
dependencies = [
"pycparser",
]
[[package]]
name = "click"
version = "8.1.3"
requires_python = ">=3.7"
summary = "Composable command line interface toolkit"
dependencies = [
"colorama; platform_system == \"Windows\"",
]
[[package]]
name = "colorama"
version = "0.4.5"
requires_python = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
summary = "Cross-platform colored terminal text."
[[package]]
name = "commonmark"
version = "0.9.1"
summary = "Python parser for the CommonMark Markdown spec"
[[package]]
name = "debugpy"
version = "1.6.3"
requires_python = ">=3.7"
summary = "An implementation of the Debug Adapter Protocol for Python"
[[package]]
name = "decorator"
version = "5.1.1"
requires_python = ">=3.5"
summary = "Decorators for Humans"
[[package]]
name = "entrypoints"
version = "0.4"
requires_python = ">=3.6"
summary = "Discover and load entry points from installed packages."
[[package]]
name = "executing"
version = "0.10.0"
summary = "Get the currently executing AST node of a frame, and other information"
[[package]]
name = "h11"
version = "0.12.0"
requires_python = ">=3.6"
summary = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1"
[[package]]
name = "httpcore"
version = "0.15.0"
requires_python = ">=3.7"
summary = "A minimal low-level HTTP client."
dependencies = [
"anyio==3.*",
"certifi",
"h11<0.13,>=0.11",
"sniffio==1.*",
]
[[package]]
name = "httpx"
version = "0.23.0"
requires_python = ">=3.7"
summary = "The next generation HTTP client."
dependencies = [
"certifi",
"httpcore<0.16.0,>=0.15.0",
"rfc3986[idna2008]<2,>=1.3",
"sniffio",
]
[[package]]
name = "idna"
version = "3.3"
requires_python = ">=3.5"
summary = "Internationalized Domain Names in Applications (IDNA)"
[[package]]
name = "ipykernel"
version = "6.15.1"
requires_python = ">=3.7"
summary = "IPython Kernel for Jupyter"
dependencies = [
"appnope; platform_system == \"Darwin\"",
"debugpy>=1.0",
"ipython>=7.23.1",
"jupyter-client>=6.1.12",
"matplotlib-inline>=0.1",
"nest-asyncio",
"packaging",
"psutil",
"pyzmq>=17",
"tornado>=6.1",
"traitlets>=5.1.0",
]
[[package]]
name = "ipython"
version = "8.4.0"
requires_python = ">=3.8"
summary = "IPython: Productive Interactive Computing"
dependencies = [
"appnope; sys_platform == \"darwin\"",
"backcall",
"colorama; sys_platform == \"win32\"",
"decorator",
"jedi>=0.16",
"matplotlib-inline",
"pexpect>4.3; sys_platform != \"win32\"",
"pickleshare",
"prompt-toolkit!=3.0.0,!=3.0.1,<3.1.0,>=2.0.0",
"pygments>=2.4.0",
"setuptools>=18.5",
"stack-data",
"traitlets>=5",
]
[[package]]
name = "isort"
version = "5.10.1"
requires_python = ">=3.6.1,<4.0"
summary = "A Python utility / library to sort Python imports."
[[package]]
name = "jedi"
version = "0.18.1"
requires_python = ">=3.6"
summary = "An autocompletion tool for Python that can be used for text editors."
dependencies = [
"parso<0.9.0,>=0.8.0",
]
[[package]]
name = "jupyter-client"
version = "7.3.5"
requires_python = ">=3.7"
summary = "Jupyter protocol implementation and client libraries"
dependencies = [
"entrypoints",
"jupyter-core>=4.9.2",
"nest-asyncio>=1.5.4",
"python-dateutil>=2.8.2",
"pyzmq>=23.0",
"tornado>=6.2",
"traitlets",
]
[[package]]
name = "jupyter-core"
version = "4.11.1"
requires_python = ">=3.7"
summary = "Jupyter core package. A base package on which Jupyter projects rely."
dependencies = [
"pywin32>=1.0; sys_platform == \"win32\" and platform_python_implementation != \"PyPy\"",
"traitlets",
]
[[package]]
name = "matplotlib-inline"
version = "0.1.6"
requires_python = ">=3.5"
summary = "Inline Matplotlib backend for Jupyter"
dependencies = [
"traitlets",
]
[[package]]
name = "mutagen"
version = "1.45.1"
requires_python = ">=3.5, <4"
summary = "read and write audio tags for many formats"
[[package]]
name = "mypy-extensions"
version = "0.4.3"
summary = "Experimental type system extensions for programs checked with the mypy typechecker."
[[package]]
name = "nest-asyncio"
version = "1.5.5"
requires_python = ">=3.5"
summary = "Patch asyncio to allow nested event loops"
[[package]]
name = "packaging"
version = "21.3"
requires_python = ">=3.6"
summary = "Core utilities for Python packages"
dependencies = [
"pyparsing!=3.0.5,>=2.0.2",
]
[[package]]
name = "parso"
version = "0.8.3"
requires_python = ">=3.6"
summary = "A Python Parser"
[[package]]
name = "pathspec"
version = "0.9.0"
requires_python = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7"
summary = "Utility library for gitignore style pattern matching of file paths."
[[package]]
name = "pexpect"
version = "4.8.0"
summary = "Pexpect allows easy control of interactive console applications."
dependencies = [
"ptyprocess>=0.5",
]
[[package]]
name = "pickleshare"
version = "0.7.5"
summary = "Tiny 'shelve'-like database with concurrency support"
[[package]]
name = "platformdirs"
version = "2.5.2"
requires_python = ">=3.7"
summary = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
[[package]]
name = "prompt-toolkit"
version = "3.0.30"
requires_python = ">=3.6.2"
summary = "Library for building powerful interactive command lines in Python"
dependencies = [
"wcwidth",
]
[[package]]
name = "psutil"
version = "5.9.1"
requires_python = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
summary = "Cross-platform lib for process and system monitoring in Python."
[[package]]
name = "ptyprocess"
version = "0.7.0"
summary = "Run a subprocess in a pseudo terminal"
[[package]]
name = "pure-eval"
version = "0.2.2"
summary = "Safely evaluate AST nodes without side effects"
[[package]]
name = "py"
version = "1.11.0"
requires_python = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
summary = "library with cross-python path, ini-parsing, io, code, log facilities"
[[package]]
name = "pycparser"
version = "2.21"
requires_python = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
summary = "C parser in Python"
[[package]]
name = "pydantic"
version = "1.9.2"
requires_python = ">=3.6.1"
summary = "Data validation and settings management using python type hints"
dependencies = [
"typing-extensions>=3.7.4.3",
]
[[package]]
name = "pygments"
version = "2.13.0"
requires_python = ">=3.6"
summary = "Pygments is a syntax highlighting package written in Python."
[[package]]
name = "pyparsing"
version = "3.0.9"
requires_python = ">=3.6.8"
summary = "pyparsing module - Classes and methods to define and execute parsing grammars"
[[package]]
name = "python-dateutil"
version = "2.8.2"
requires_python = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7"
summary = "Extensions to the standard Python datetime module"
dependencies = [
"six>=1.5",
]
[[package]]
name = "pywin32"
version = "304"
summary = "Python for Window Extensions"
[[package]]
name = "pyzmq"
version = "23.2.1"
requires_python = ">=3.6"
summary = "Python bindings for 0MQ"
dependencies = [
"cffi; implementation_name == \"pypy\"",
"py; implementation_name == \"pypy\"",
]
[[package]]
name = "rfc3986"
version = "1.5.0"
summary = "Validating URI References per RFC 3986"
[[package]]
name = "rfc3986"
version = "1.5.0"
extras = ["idna2008"]
summary = "Validating URI References per RFC 3986"
dependencies = [
"idna",
"rfc3986==1.5.0",
]
[[package]]
name = "rich"
version = "12.5.1"
requires_python = ">=3.6.3,<4.0.0"
summary = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal"
dependencies = [
"commonmark<0.10.0,>=0.9.0",
"pygments<3.0.0,>=2.6.0",
]
[[package]]
name = "setuptools"
version = "65.3.0"
requires_python = ">=3.7"
summary = "Easily download, build, install, upgrade, and uninstall Python packages"
[[package]]
name = "six"
version = "1.16.0"
requires_python = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*"
summary = "Python 2 and 3 compatibility utilities"
[[package]]
name = "sniffio"
version = "1.2.0"
requires_python = ">=3.5"
summary = "Sniff out which async library your code is running under"
[[package]]
name = "stack-data"
version = "0.5.0"
summary = "Extract data from python stack frames and tracebacks for informative displays"
dependencies = [
"asttokens",
"executing",
"pure-eval",
]
[[package]]
name = "tomli"
version = "2.0.1"
requires_python = ">=3.7"
summary = "A lil' TOML parser"
[[package]]
name = "tornado"
version = "6.2"
requires_python = ">= 3.7"
summary = "Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed."
[[package]]
name = "traitlets"
version = "5.3.0"
requires_python = ">=3.7"
summary = ""
[[package]]
name = "typing-extensions"
version = "4.3.0"
requires_python = ">=3.7"
summary = "Backported and Experimental Type Hints for Python 3.7+"
[[package]]
name = "wcwidth"
version = "0.2.5"
summary = "Measures the displayed width of unicode strings in a terminal"
[metadata]
lock_version = "4.0"
content_hash = "sha256:139fe20b05d252b2a5f9d0210eba30c4ac9c44c2709d60f3b62fec34456b3257"
[metadata.files]
"anyio 3.6.1" = [
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/0f/60/ae005e0c88703f49c2047af8e83ede692704577599c4e488cc6e9ef7ffb6/anyio-3.3.3.tar.gz", hash = "sha256:8eccec339cb4a856c94a75d50fc1d451faf32a05ef406be462e2efc59c9838b0"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/15/34/2e0a5d81a92f29d6e90f096182612411955677eb80986c745bdeb7326424/anyio-3.0.1.tar.gz", hash = "sha256:1ef7622396ab55829d4236a6f75e2199df6d26a4ba79bea0cb942a5fd2f79a23"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/23/75/8d31e0de8c87cb17aecde237def16383569737ae9e15d99ac54eafc61f78/anyio-3.0.1-py3-none-any.whl", hash = "sha256:ed71f7542ef39875b65def219794d9dcb0a48c571317b13612c12b1f292701b5"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/2b/e3/f23b7986619c7de90f63b1ac898074ddd9641e70e1677eec3d9f40969aa3/anyio-3.6.0.tar.gz", hash = "sha256:056bd22787f4bc59cb6d9a6873929618c2233d64903eed64177070fd072bd9ca"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/2f/c0/33f00b43a3bc47ce8214863d5d75b250fb6901fb83f3c41f1081f6a3558a/anyio-3.2.0-py3-none-any.whl", hash = "sha256:89e19b1498c8a6f12277e0bd2949597e445aa1b14361fbab2c36943639ef5190"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/39/91/871a857350359cc2f399763fa0865aec4de5d12845261dcbf5a8ebf1b8b8/anyio-3.1.0.tar.gz", hash = "sha256:43e20711a9d003d858d694c12356dc44ab82c03ccc5290313c3392fa349dad0e"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/3b/49/ebee263b69fe243bd1fd0a88bc6bb0f7732bf1794ba3273cb446351f9482/anyio-3.0.0-py3-none-any.whl", hash = "sha256:e71c3d9d72291d12056c0265d07c6bbedf92332f78573e278aeb116f24f30395"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/4f/d0/b957c0679a9bd0ed334e2e584102f077c3e703f83d099464c3d9569b7c8a/anyio-3.5.0.tar.gz", hash = "sha256:a0aeffe2fb1fdf374a8e4b471444f0f3ac4fb9f5a5b542b48824475e0042a5a6"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/58/92/29df8cc2d38a54c1db0074bc745109b30edbcccf3ebac7c3c82c63cd692c/anyio-3.3.0.tar.gz", hash = "sha256:ae57a67583e5ff8b4af47666ff5651c3732d45fd26c929253748e796af860374"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/5a/8c/6712b0aebe9b250736ec5dde99883b143290b49ecc2310eb583577e316aa/anyio-3.2.1-py3-none-any.whl", hash = "sha256:442678a3c7e1cdcdbc37dcfe4527aa851b1b0c9162653b516e9f509821691d50"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/66/02/ca9061e93c487a897859e3a41f6c1a4f494038d2791382169b9a0c528175/anyio-3.3.4.tar.gz", hash = "sha256:67da67b5b21f96b9d3d65daa6ea99f5d5282cb09f50eb4456f8fb51dffefc3ff"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/67/c4/fd50bbb2fb72532a4b778562e28ba581da15067cfb2537dbd3a2e64689c1/anyio-3.6.1.tar.gz", hash = "sha256:413adf95f93886e442aea925f3ee43baa5a765a64a0f52c6081894f9992fdd0b"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/72/47/0c30d51c30d23eecead360e8624ad3972ebd8f9933265a91fca1372d37cf/anyio-3.1.0-py3-none-any.whl", hash = "sha256:5e335cef65fbd1a422bbfbb4722e8e9a9fadbd8c06d5afe9cd614d12023f6e5a"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/89/c7/76b61d971bd463ed32d093c61a70d757a8edd7f7baaec0bdabc64ed9f376/anyio-3.3.2-py3-none-any.whl", hash = "sha256:c32da314c510b34a862f5afeaf8a446ffed2c2fde21583e654bd71ecfb5b744b"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/94/72/c728ad9e34f53be06f4dfbff4d511907bafb46920f10dc34836e58bd6894/anyio-3.3.0-py3-none-any.whl", hash = "sha256:929a6852074397afe1d989002aa96d457e3e1e5441357c60d03e7eea0e65e1b0"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/98/3e/1432e7d8d9f71676d6638b4feb6285f53575239f7b527a95e85b7e888bba/anyio-3.3.1-py3-none-any.whl", hash = "sha256:d7c604dd491eca70e19c78664d685d5e4337612d574419d503e76f5d7d1590bd"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/99/0d/65165f99e5f4f3b4c43a5ed9db0fb7aa655f5a58f290727a30528a87eb45/anyio-3.0.0.tar.gz", hash = "sha256:b553598332c050af19f7d41f73a7790142f5bc3d5eb8bd82f5e515ec22019bd9"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/a4/37/76e3079bec52878b6ab45f55f9f7b2b9d6aa1458cdb018ae42594e0a5909/anyio-3.2.0.tar.gz", hash = "sha256:41c4be842c284222b197a625d76a7ab85adf9d52788f563172fe180c2744b6c1"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/a9/9a/36fca955726d572827b0f8b039a544311c362b55868fbc265bac7455e166/anyio-3.3.3-py3-none-any.whl", hash = "sha256:56ceaeed2877723578b1341f4f68c29081db189cfb40a97d1922b9513f6d7db6"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/ad/0a/919c040f061bc31f604ee8275ada8fa9f6f237425010afa523e429a04a45/anyio-3.4.0-py3-none-any.whl", hash = "sha256:2855a9423524abcdd652d942f8932fda1735210f77a6b392eafd9ff34d3fe020"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/b1/ae/9a8af72d6f0c551943903eefcf93c3a29898fb7b594603c0d70679c199b1/anyio-3.5.0-py3-none-any.whl", hash = "sha256:b5fa16c5ff93fa1046f2eeb5bbff2dad4d3514d6cda61d02816dba34fa8c3c2e"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/bf/3f/4d9972a2190759ac2a576c8fa8b64102a11932ccfb10ed928a116e283f5c/anyio-3.3.2.tar.gz", hash = "sha256:0b993a2ef6c1dc456815c2b5ca2819f382f20af98087cc2090a4afed3a501436"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/c3/22/4cba7e1b4f45ffbefd2ca817a6800ba1c671c26f288d7705f20289872012/anyio-3.6.1-py3-none-any.whl", hash = "sha256:cb29b9c70620506a9a8f87a309591713446953302d7d995344d0d7c6c0c9a7be"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/d9/f5/180f7b4c3b2fcdc79e8f71c71c7c3de575d5d08bdb27ee145d23801539db/anyio-3.3.1.tar.gz", hash = "sha256:85913b4e2fec030e8c72a8f9f98092eeb9e25847a6e00d567751b77e34f856fe"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/dc/e7/7452227e8c091db6838d7f1b50dc4e6323e8463ed8c2d0b651ac9b7f7fce/anyio-3.4.0.tar.gz", hash = "sha256:24adc69309fb5779bc1e06158e143e0b6d2c56b302a3ac3de3083c705a6ed39d"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/e6/bc/832d33ddcf7bcfdfa73cd1780847726dee4581adac9d4ca975feb8e7662c/anyio-3.3.4-py3-none-any.whl", hash = "sha256:4fd09a25ab7fa01d34512b7249e366cd10358cdafc95022c7ff8c8f8a5026d66"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/f4/17/86c924b1371353f785e1515b830e118fcd46880ae8d7a7b11116e5f81d6f/anyio-3.6.0-py3-none-any.whl", hash = "sha256:5bd42d66c9c382e657c9acba60f9459d747c192513e76dcae8b1c611e55174ef"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/ff/b7/9730df0dd70a2d77bc03fb5e3dca62735fc6b39719a62eb7785ef070d07e/anyio-3.2.1.tar.gz", hash = "sha256:07968db9fa7c1ca5435a133dc62f988d84ef78e1d9b22814a59d1c62618afbc5"},
]
"appnope 0.1.3" = [
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/41/4a/381783f26df413dde4c70c734163d88ca0550a1361cb74a1c68f47550619/appnope-0.1.3-py2.py3-none-any.whl", hash = "sha256:265a455292d0bd8a72453494fa24df5a11eb18373a60c7c0430889f22548605e"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/6a/cd/355842c0db33192ac0fc822e2dcae835669ef317fe56c795fb55fcddb26f/appnope-0.1.3.tar.gz", hash = "sha256:02bd91c4de869fbb1e1c50aafc4098827a7a54ab2f39d9dcba6c9547ed920e24"},
]
"asttokens 2.0.8" = [
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/2d/1b/fdbdf82b86e07ca90985740ac160a1dd4ab09cb81071ec12d71c701e1138/asttokens-2.0.8-py2.py3-none-any.whl", hash = "sha256:e3305297c744ae53ffa032c45dc347286165e4ffce6875dc662b205db0623d86"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/4d/c8/987ee029c83ad1cddb03bb004e9c7a8de1be4cdbda21122a0b9f639fcc31/asttokens-2.0.8.tar.gz", hash = "sha256:c61e16246ecfb2cde2958406b4c8ebc043c9e6d73aaa83c941673b35e5d3a76b"},
]
"backcall 0.2.0" = [
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/4c/1c/ff6546b6c12603d8dd1070aa3c3d273ad4c07f5771689a7b69a550e8c951/backcall-0.2.0-py2.py3-none-any.whl", hash = "sha256:fbbce6a29f263178a1f7915c1940bde0ec2b2a967566fe1c65c1dfb7422bd255"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/a2/40/764a663805d84deee23043e1426a9175567db89c8b3287b5c2ad9f71aa93/backcall-0.2.0.tar.gz", hash = "sha256:5cbdbf27be5e7cfadb448baf0aa95508f91f2bbc6c6437cd9cd06e2a4c215e1e"},
]
"black 22.6.0" = [
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/07/eb/a757135497a3be31ab8c00ef239070c7277ad11b618104950a756bcab3c1/black-22.6.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:a218d7e5856f91d20f04e931b6f16d15356db1c846ee55f01bac297a705ca24f"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/19/b0/13864fd5f3090ca5379f3dcf6034f1e4f02b59620e7b8b5c6f0c85622c0b/black-22.6.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:560558527e52ce8afba936fcce93a7411ab40c7d5fe8c2463e279e843c0328ee"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/1a/84/203163902ee26bcf1beaef582ee0c8df3f325da3e961b68d2ece959e19d3/black-22.6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6797f58943fceb1c461fb572edbe828d811e719c24e03375fd25170ada53825e"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/1d/d2/bc58bae8ec35f5a3c796d71d5bda113060678483e623a019fb889edd8d97/black-22.6.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7ba9be198ecca5031cd78745780d65a3f75a34b2ff9be5837045dce55db83d1c"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/2b/70/1d0e33a4df4ed73e9f02f698a29b5d94ff58e39f029c939ecf96a10fb1f3/black-22.6.0-py3-none-any.whl", hash = "sha256:ac609cf8ef5e7115ddd07d85d988d074ed00e10fbc3445aee393e70164a2219c"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/2b/d9/7331e50dad8d5149a9e2285766960ac6b732ae9b3b9796e10916ad88ff61/black-22.6.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b154e6bbde1e79ea3260c4b40c0b7b3109ffcdf7bc4ebf8859169a6af72cd70b"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/3e/fd/5e47b4d77549909e484de906a69fccc3fcfb782131d8b449073ad8b3ed3e/black-22.6.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:568ac3c465b1c8b34b61cd7a4e349e93f91abf0f9371eda1cf87194663ab684e"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/40/d1/3f366d7887d1fb6e3e487a6c975a9e9e13618757ed0d5427197fa9e28290/black-22.6.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:187d96c5e713f441a5829e77120c269b6514418f4513a390b0499b0987f2ff1c"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/46/eb/f489451de8b3e91bd82ee722b9a8493b94f8719ea6649e5b8bba2376056d/black-22.6.0-cp37-cp37m-win_amd64.whl", hash = "sha256:074458dc2f6e0d3dab7928d4417bb6957bb834434516f21514138437accdbe90"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/55/33/752544332a2d3be0f6d54ef808075681b68ddc15cfcb90ff128f2d30c85c/black-22.6.0-cp39-cp39-win_amd64.whl", hash = "sha256:4af5bc0e1f96be5ae9bd7aaec219c901a94d6caa2484c21983d043371c733fc4"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/57/62/2961a0a57bdf768ccb5aea16327400be6e6bde4fb47ac05af7e9535c5289/black-22.6.0-cp36-cp36m-win_amd64.whl", hash = "sha256:2ea29072e954a4d55a2ff58971b83365eba5d3d357352a07a7a4df0d95f51c78"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/61/11/551b0d067a7e6836fc0997ab36ee46ec65259fea8f30104f4870092f3301/black-22.6.0.tar.gz", hash = "sha256:6c6d39e28aed379aec40da1c65434c77d75e65bb59a1e1c283de545fb4e7c6c9"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/63/96/814e02033701f51701444d5505b5e2594453b1f7e913764a097b1f701633/black-22.6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b270a168d69edb8b7ed32c193ef10fd27844e5c60852039599f9184460ce0807"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/80/ff/cfcfa4cdb42d8fff75b6b4dc355a1186a95de4714df8cc2a60f69f7b17f8/black-22.6.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:f586c26118bc6e714ec58c09df0157fe2d9ee195c764f630eb0d8e7ccce72e69"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/86/9c/2a8a13993bc63a50bda7436ecba902231fd9a88dd1cd233e6e3f534e071c/black-22.6.0-cp310-cp310-win_amd64.whl", hash = "sha256:f6fe02afde060bbeef044af7996f335fbe90b039ccf3f5eb8f16df8b20f77666"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/8a/90/69274ed80397ada663ce3c4cc0c70b7fb20b529f9baf4bf9ddf4edc14ccd/black-22.6.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:cfaf3895a9634e882bf9d2363fed5af8888802d670f58b279b0bece00e9a872d"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/9b/22/ff6d904dcb6f92bd7c20b178ed0aa9e6814ae6452df6c573806dbc465b85/black-22.6.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a3db5b6409b96d9bd543323b23ef32a1a2b06416d525d27e0f67e74f1446c8f2"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/a7/51/d0acd9f74a946a825a148dcc392433c2332ae405967d76292b9e64712dc8/black-22.6.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c85928b9d5f83b23cee7d0efcb310172412fbf7cb9d9ce963bd67fd141781def"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/ac/9d/b06f45e8dff2b10bf4644ba7a74490538c0272ae48308e04c6f551671b89/black-22.6.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:e439798f819d49ba1c0bd9664427a05aab79bfba777a6db94fd4e56fae0cb849"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/c4/67/a4e9125bf1a4eb5a2624b3b979af2dc6ee8d3c4ee0b3d2867173db4916fa/black-22.6.0-cp38-cp38-win_amd64.whl", hash = "sha256:b9fd45787ba8aa3f5e0a0a98920c1012c884622c6c920dbe98dbd05bc7c70fbf"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/d6/45/985c13ac6b2f67504cda61fc1d95365eb6446a4c6988ffe0f0f311f7a617/black-22.6.0-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:94783f636bca89f11eb5d50437e8e17fbc6a929a628d82304c80fa9cd945f256"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/e7/fe/4533d110ddced851a359cbbb162685814719690ee01939a34be023410854/black-22.6.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:6c1734ab264b8f7929cef8ae5f900b85d579e6cbfde09d7387da8f04771b51c6"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/fc/37/032c45b55f901ee3fe780fbc17fe2dc262c809d94de1288201350d8d680b/black-22.6.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c9a3ac16efe9ec7d7381ddebcc022119794872abce99475345c5a61aa18c45ad"},
]
"certifi 2022.6.15" = [
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/cc/85/319a8a684e8ac6d87a1193090e06b6bbb302717496380e225ee10487c888/certifi-2022.6.15.tar.gz", hash = "sha256:84c85a9078b11105f04f3036a9482ae10e4621616db313fe045dd24743a0820d"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/e9/06/d3d367b7af6305b16f0d28ae2aaeb86154fa91f144f036c2d5002a5a202b/certifi-2022.6.15-py3-none-any.whl", hash = "sha256:fe86415d55e84719d75f8b69414f6438ac3547d2078ab91b67e779ef69378412"},
]
"cffi 1.15.1" = [
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/00/05/23a265a3db411b0bfb721bf7a116c7cecaf3eb37ebd48a6ea4dfb0a3244d/cffi-1.15.1-cp27-cp27m-win_amd64.whl", hash = "sha256:e00b098126fd45523dd056d2efba6c5a63b71ffe9f2bbe1a4fe1716e1d0c331e"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/03/7b/259d6e01a6083acef9d3c8c88990c97d313632bb28fa84d6ab2bb201140a/cffi-1.15.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:173379135477dc8cac4bc58f45db08ab45d228b3363adb7af79436135d028405"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/0e/65/0d7b5dad821ced4dcd43f96a362905a68ce71e6b5f5cfd2fada867840582/cffi-1.15.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:59c0b02d0a6c384d453fece7566d1c7e6b7bae4fc5874ef2ef46d56776d61c9e"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/0e/e2/a23af3d81838c577571da4ff01b799b0c2bbde24bd924d97e228febae810/cffi-1.15.1-cp310-cp310-win_amd64.whl", hash = "sha256:ce4bcc037df4fc5e3d184794f27bdaab018943698f4ca31630bc7f84a7b69c6d"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/10/72/617ee266192223a38b67149c830bd9376b69cf3551e1477abc72ff23ef8e/cffi-1.15.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a591fe9e525846e4d154205572a029f653ada1a78b93697f3b5a8f1f2bc055b9"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/18/8f/5ff70c7458d61fa8a9752e5ee9c9984c601b0060aae0c619316a1e1f1ee5/cffi-1.15.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:54a2db7b78338edd780e7ef7f9f6c442500fb0d41a5a4ea24fff1c929d5af585"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/1d/76/bcebbbab689f5f6fc8a91e361038a3001ee2e48c5f9dbad0a3b64a64cc9e/cffi-1.15.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:9ad5db27f9cabae298d151c85cf2bad1d359a1b9c686a275df03385758e2f914"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/22/c6/df826563f55f7e9dd9a1d3617866282afa969fe0d57decffa1911f416ed8/cffi-1.15.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e74c6b51a9ed6589199c787bf5f9875612ca4a8a0785fb2d4a84429badaf22a"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/23/8b/2e8c2469eaf89f7273ac685164949a7e644cdfe5daf1c036564208c3d26b/cffi-1.15.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3d08afd128ddaa624a48cf2b859afef385b720bb4b43df214f85616922e6a5ac"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/2b/a8/050ab4f0c3d4c1b8aaa805f70e26e84d0e27004907c5b8ecc1d31815f92a/cffi-1.15.1.tar.gz", hash = "sha256:d400bfb9a37b1351253cb402671cea7e89bdecc294e8016a707f6d1d8ac934f9"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/2d/86/3ca57cddfa0419f6a95d1c8478f8f622ba597e3581fd501bbb915b20eb75/cffi-1.15.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5d598b938678ebf3c67377cdd45e09d431369c3b1a5b331058c338e201f12b27"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/2e/7a/68c35c151e5b7a12650ecc12fdfb85211aa1da43e9924598451c4a0a3839/cffi-1.15.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a8c4917bd7ad33e8eb21e9a5bbba979b49d9a97acb3a803092cbc1133e20343c"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/32/2a/63cb8c07d151de92ff9d897b2eb27ba6a0e78dda8e4c5f70d7b8c16cd6a2/cffi-1.15.1-cp37-cp37m-win_amd64.whl", hash = "sha256:a0b71b1b8fbf2b96e41c4d990244165e2c9be83d54962a9a1d118fd8657d2045"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/32/bd/d0809593f7976828f06a492716fbcbbfb62798bbf60ea1f65200b8d49901/cffi-1.15.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:fa6693661a4c91757f4412306191b6dc88c1703f780c8234035eac011922bc01"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/37/5a/c37631a86be838bdd84cc0259130942bf7e6e32f70f4cab95f479847fb91/cffi-1.15.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:94411f22c3985acaec6f83c6df553f2dbe17b698cc7f8ae751ff2237d96b9e3c"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/3a/12/d6066828014b9ccb2bbb8e1d9dc28872d20669b65aeb4a86806a0757813f/cffi-1.15.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:6975a3fac6bc83c4a65c9f9fcab9e47019a11d3d2cf7f3c0d03431bf145a941e"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/3a/75/a162315adeaf47e94a3b7f886a8e31d77b9e525a387eef2d6f0efc96a7c8/cffi-1.15.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:fcd131dd944808b5bdb38e6f5b53013c5aa4f334c5cad0c72742f6eba4b73db0"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/3f/fa/dfc242febbff049509e5a35a065bdc10f90d8c8585361c2c66b9c2f97a01/cffi-1.15.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:a66d3508133af6e8548451b25058d5812812ec3798c886bf38ed24a98216fab2"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/43/a0/cc7370ef72b6ee586369bacd3961089ab3d94ae712febf07a244f1448ffd/cffi-1.15.1-cp311-cp311-win_amd64.whl", hash = "sha256:04ed324bda3cda42b9b695d51bb7d54b680b9719cfab04227cdd1e04e5de3104"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/47/51/3049834f07cd89aceef27f9c56f5394ca6725ae6a15cff5fbdb2f06a24ad/cffi-1.15.1-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cec7d9412a9102bdc577382c3929b337320c4c4c4849f2c5cdd14d7368c5562d"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/47/97/137f0e3d2304df2060abb872a5830af809d7559a5a4b6a295afb02728e65/cffi-1.15.1-cp38-cp38-win32.whl", hash = "sha256:8b7ee99e510d7b66cdb6c593f21c043c248537a32e0bedf02e01e9553a172314"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/50/34/4cc590ad600869502c9838b4824982c122179089ed6791a8b1c95f0ff55e/cffi-1.15.1-cp37-cp37m-win32.whl", hash = "sha256:e229a521186c75c8ad9490854fd8bbdd9a0c9aa3a524326b55be83b54d4e0ad9"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/5b/1a/e1ee5bed11d8b6540c05a8e3c32448832d775364d4461dd6497374533401/cffi-1.15.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8102eaf27e1e448db915d08afa8b41d6c7ca7a04b7d73af6514df10a3e74bd82"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/5d/4e/4e0bb5579b01fdbfd4388bd1eb9394a989e1336203a4b7f700d887b233c1/cffi-1.15.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:91fc98adde3d7881af9b59ed0294046f3806221863722ba7d8d120c575314325"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/5d/6f/3a2e167113eabd46ed300ff3a6a1e9277a3ad8b020c4c682f83e9326fcf7/cffi-1.15.1-cp36-cp36m-win32.whl", hash = "sha256:2470043b93ff09bf8fb1d46d1cb756ce6132c54826661a32d4e4d132e1977adf"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/69/bf/335f8d95510b1a26d7c5220164dc739293a71d5540ecd54a2f66bac3ecb8/cffi-1.15.1-cp36-cp36m-win_amd64.whl", hash = "sha256:30d78fbc8ebf9c92c9b7823ee18eb92f2e6ef79b45ac84db507f52fbe3ec4497"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/71/d7/0fe0d91b0bbf610fb7254bb164fa8931596e660d62e90fb6289b7ee27b09/cffi-1.15.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:03425bdae262c76aad70202debd780501fabeaca237cdfddc008987c0e0f59ef"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/77/b7/d3618d612be01e184033eab90006f8ca5b5edafd17bf247439ea4e167d8a/cffi-1.15.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6c9a799e985904922a4d207a94eae35c78ebae90e128f0c4e521ce339396be9d"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/79/4b/33494eb0adbcd884656c48f6db0c98ad8a5c678fb8fb5ed41ab546b04d8c/cffi-1.15.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:87c450779d0914f2861b8526e035c5e6da0a3199d8f1add1a665e1cbc6fc6d02"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/7c/3e/5d823e5bbe00285e479034bcad44177b7353ec9fdcd7795baac5ccf82950/cffi-1.15.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50a74364d85fd319352182ef59c5c790484a336f6db772c1a9231f1c3ed0cbd7"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/85/1f/a3c533f8d377da5ca7edb4f580cc3edc1edbebc45fac8bb3ae60f1176629/cffi-1.15.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7473e861101c9e72452f9bf8acb984947aa1661a7704553a9f6e4baa5ba64415"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/87/4b/64e8bd9d15d6b22b6cb11997094fbe61edf453ea0a97c8675cb7d1c3f06f/cffi-1.15.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:320dab6e7cb2eacdf0e658569d2575c4dad258c0fcc794f46215e1e39f90f2c3"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/87/ee/ddc23981fc0f5e7b5356e98884226bcb899f95ebaefc3e8e8b8742dd7e22/cffi-1.15.1-cp311-cp311-win32.whl", hash = "sha256:a0f100c8912c114ff53e1202d0078b425bee3649ae34d7b070e9697f93c5d52d"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/88/89/c34caf63029fb7628ec2ebd5c88ae0c9bd17db98c812e4065a4d020ca41f/cffi-1.15.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd86c085fae2efd48ac91dd7ccffcfc0571387fe1193d33b6394db7ef31fe2a4"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/91/bc/b7723c2fe7a22eee71d7edf2102cd43423d5f95ff3932ebaa2f82c7ec8d0/cffi-1.15.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3548db281cd7d2561c9ad9984681c95f7b0e38881201e157833a2342c30d5e8c"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/93/d0/2e2b27ea2f69b0ec9e481647822f8f77f5fc23faca2dd00d1ff009940eb7/cffi-1.15.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e2642fe3142e4cc4af0799748233ad6da94c62a8bec3a6648bf8ee68b1c7426"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/9f/52/1e2b43cfdd7d9a39f48bc89fcaee8d8685b1295e205a4f1044909ac14d89/cffi-1.15.1-cp310-cp310-win32.whl", hash = "sha256:cba9d6b9a7d64d4bd46167096fc9d2f835e25d7e4c121fb2ddfc6528fb0413b2"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/a4/42/54bdf22cf6c8f95113af645d0bd7be7f9358ea5c2d57d634bb11c6b4d0b2/cffi-1.15.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:ed9cb427ba5504c1dc15ede7d516b84757c3e3d7868ccc85121d9310d27eed0b"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/a8/16/06b84a7063a4c0a2b081030fdd976022086da9c14e80a9ed4ba0183a98a9/cffi-1.15.1-cp39-cp39-win_amd64.whl", hash = "sha256:70df4e3b545a17496c9b3f41f5115e69a4f2e77e94e1d2a8e1070bc0c38c8a3c"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/a9/ba/e082df21ebaa9cb29f2c4e1d7e49a29b90fcd667d43632c6674a16d65382/cffi-1.15.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3bcde07039e586f91b45c88f8583ea7cf7a0770df3a1649627bf598332cb6984"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/aa/02/ab15b3aa572759df752491d5fa0f74128cd14e002e8e3257c1ab1587810b/cffi-1.15.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2012c72d854c2d03e45d06ae57f40d78e5770d252f195b93f581acf3ba44496e"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/ad/26/7b3a73ab7d82a64664c7c4ea470e4ec4a3c73bb4f02575c543a41e272de5/cffi-1.15.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:db0fbb9c62743ce59a9ff687eb5f4afbe77e5e8403d6697f7446e5f609976f76"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/af/cb/53b7bba75a18372d57113ba934b27d0734206c283c1dfcc172347fbd9f76/cffi-1.15.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:33ab79603146aace82c2427da5ca6e58f2b3f2fb5da893ceac0c42218a40be35"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/af/da/9441d56d7dd19d07dcc40a2a5031a1f51c82a27cee3705edf53dadcac398/cffi-1.15.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5635bd9cb9731e6d4a1132a498dd34f764034a8ce60cef4f5319c0541159392f"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/b3/b8/89509b6357ded0cbacc4e430b21a4ea2c82c2cdeb4391c148b7c7b213bed/cffi-1.15.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4289fc34b2f5316fbb762d75362931e351941fa95fa18789191b33fc4cf9504a"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/b5/7d/df6c088ef30e78a78b0c9cca6b904d5abb698afb5bc8f5191d529d83d667/cffi-1.15.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:198caafb44239b60e252492445da556afafc7d1e3ab7a1fb3f0584ef6d742375"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/b5/80/ce5ba093c2475a73df530f643a61e2969a53366e372b24a32f08cd10172b/cffi-1.15.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e263d77ee3dd201c3a142934a086a4450861778baaeeb45db4591ef65550b0a6"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/b7/8b/06f30caa03b5b3ac006de4f93478dbd0239e2a16566d81a106c322dc4f79/cffi-1.15.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f2c9f67e9821cad2e5f480bc8d83b8742896f1242dba247911072d4fa94c192"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/b9/4a/dde4d093a3084d0b0eadfb2703f71e31a5ced101a42c839ac5bbbd1710f2/cffi-1.15.1-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:d61f4695e6c866a23a21acab0509af1cdfd2c013cf256bbf5b6b5e2695827162"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/c1/25/16a082701378170559bb1d0e9ef2d293cece8dc62913d79351beb34c5ddf/cffi-1.15.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5c84c68147988265e60416b57fc83425a78058853509c1b0629c180094904a5"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/c2/0b/3b09a755ddb977c167e6d209a7536f6ade43bb0654bad42e08df1406b8e4/cffi-1.15.1-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5ef34d190326c3b1f822a5b7a45f6c4535e2f47ed06fec77d3d799c450b2651e"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/c5/ff/3f9d73d480567a609e98beb0c64359f8e4f31cb6a407685da73e5347b067/cffi-1.15.1-cp27-cp27m-win32.whl", hash = "sha256:b3bbeb01c2b273cca1e1e0c5df57f12dce9a4dd331b4fa1635b8bec26350bde3"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/c6/3d/dd085bb831b22ce4d0b7ba8550e6d78960f02f770bbd1314fea3580727f8/cffi-1.15.1-cp39-cp39-win32.whl", hash = "sha256:40f4774f5a9d4f5e344f31a32b5096977b5d48560c5592e2f3d2c4374bd543ee"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/c9/e3/0a52838832408cfbbf3a59cb19bcd17e64eb33795c9710ca7d29ae10b5b7/cffi-1.15.1-cp38-cp38-win_amd64.whl", hash = "sha256:00a9ed42e88df81ffae7a8ab6d9356b371399b91dbdf0c3cb1e84c03a13aceb5"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/d3/56/3e94aa719ae96eeda8b68b3ec6e347e0a23168c6841dc276ccdcdadc9f32/cffi-1.15.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:cc4d65aeeaa04136a12677d3dd0b1c0c94dc43abac5860ab33cceb42b801c1e8"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/d3/e1/e55ca2e0dd446caa2cc8f73c2b98879c04a1f4064ac529e1836683ca58b8/cffi-1.15.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5df2768244d19ab7f60546d0c7c63ce1581f7af8b5de3eb3004b9b6fc8a9f84b"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/da/ff/ab939e2c7b3f40d851c0f7192c876f1910f3442080c9c846532993ec3cef/cffi-1.15.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:98d85c6a2bef81588d9227dde12db8a7f47f639f4a17c9ae08e773aa9c697bf3"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/df/02/aef53d4aa43154b829e9707c8c60bab413cd21819c4a36b0d7aaa83e2a61/cffi-1.15.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3b926aa83d1edb5aa5b427b4053dc420ec295a08e40911296b9eb1b6170f6cca"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/e8/ff/c4b7a358526f231efa46a375c959506c87622fb4a2c5726e827c55e6adf2/cffi-1.15.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:39d39875251ca8f612b6f33e6b1195af86d1b3e60086068be9cc053aa4376e21"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/ea/be/c4ad40ad441ac847b67c7a37284ae3c58f39f3e638c6b0f85fb662233825/cffi-1.15.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:285d29981935eb726a4399badae8f0ffdff4f5050eaa6d0cfc3f64b857b77185"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/ed/a3/c5f01988ddb70a187c3e6112152e01696188c9f8a4fa4c68aa330adbb179/cffi-1.15.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3eb6971dcff08619f8d91607cfc726518b6fa2a9eba42856be181c6d0d9515fd"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/ef/41/19da352d341963d29a33bdb28433ba94c05672fb16155f794fad3fd907b0/cffi-1.15.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:21157295583fe8943475029ed5abdcf71eb3911894724e360acff1d61c1d54bc"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/f9/96/fc9e118c47b7adc45a0676f413b4a47554e5f3b6c99b8607ec9726466ef1/cffi-1.15.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3799aecf2e17cf585d977b780ce79ff0dc9b78d799fc694221ce814c2c19db83"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/ff/fe/ac46ca7b00e9e4f9c62e7928a11bc9227c86e2ff43526beee00cdfb4f0e8/cffi-1.15.1-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:470c103ae716238bbe698d67ad020e1db9d9dba34fa5a899b5e21577e6d52ed2"},
]
"click 8.1.3" = [
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/59/87/84326af34517fca8c58418d148f2403df25303e02736832403587318e9e8/click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/c2/f1/df59e28c642d583f7dacffb1e0965d0e00b218e0186d7858ac5233dce840/click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"},
]
"colorama 0.4.5" = [
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/2b/65/24d033a9325ce42ccbfa3ca2d0866c7e89cc68e5b9d92ecaba9feef631df/colorama-0.4.5.tar.gz", hash = "sha256:e6c6b4334fc50988a639d9b98aa429a0b57da6e17b9a44f0451f930b6967b7a4"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/77/8b/7550e87b2d308a1b711725dfaddc19c695f8c5fa413c640b2be01662f4e6/colorama-0.4.5-py2.py3-none-any.whl", hash = "sha256:854bf444933e37f5824ae7bfc1e98d5bce2ebe4160d46b5edf346a89358e99da"},
]
"commonmark 0.9.1" = [
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/60/48/a60f593447e8f0894ebb7f6e6c1f25dafc5e89c5879fdc9360ae93ff83f0/commonmark-0.9.1.tar.gz", hash = "sha256:452f9dc859be7f06631ddcb328b6919c67984aca654e5fefb3914d54691aed60"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/b1/92/dfd892312d822f36c55366118b95d914e5f16de11044a27cf10a7d71bbbf/commonmark-0.9.1-py2.py3-none-any.whl", hash = "sha256:da2f38c92590f83de410ba1a3cbceafbc74fee9def35f9251ba9a971d6d66fd9"},
]
"debugpy 1.6.3" = [
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/0d/54/3449fc5750a8780335ec86797d12294eb05409092ebf4539d513958eabc4/debugpy-1.6.3-cp38-cp38-win_amd64.whl", hash = "sha256:86d784b72c5411c833af1cd45b83d80c252b77c3bfdb43db17c441d772f4c734"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/26/73/43238498d39036b2c90c4ec29f64bbcee9c35c524c1176ad1ae5863119e4/debugpy-1.6.3-cp310-cp310-win_amd64.whl", hash = "sha256:dda8652520eae3945833e061cbe2993ad94a0b545aebd62e4e6b80ee616c76b2"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/3e/00/9616d339b132f80d0772c28e1119cec24a54d0b3a13a63468af23729253f/debugpy-1.6.3-cp37-cp37m-macosx_10_15_x86_64.whl", hash = "sha256:d5c814596a170a0a58fa6fad74947e30bfd7e192a5d2d7bd6a12156c2899e13a"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/5a/e6/476865a057fe515b2048d9a01b6b270a9eccbd40ec6da7dc3061476faec4/debugpy-1.6.3-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:b8deaeb779699350deeed835322730a3efec170b88927debc9ba07a1a38e2585"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/64/05/7615659abd6d927e03a33294ef75c52d056d08fc333dbcd36e2388dd7cd7/debugpy-1.6.3-cp38-cp38-win32.whl", hash = "sha256:6efc30325b68e451118b795eff6fe8488253ca3958251d5158106d9c87581bc6"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/8f/23/8dd369ef3a92bf5fdb4bf0cb84b721efbec43ae81b4f3694f6214b20d6d6/debugpy-1.6.3.zip", hash = "sha256:e8922090514a890eec99cfb991bab872dd2e353ebb793164d5f01c362b9a40bf"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/8f/db/0598efa3788f7371640cb956189d7ee41a788cce7352f7a3e5a79adae0e1/debugpy-1.6.3-cp39-cp39-win_amd64.whl", hash = "sha256:34d2cdd3a7c87302ba5322b86e79c32c2115be396f3f09ca13306d8a04fe0f16"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/92/ec/65a8c523e87a75c2dbe044196a8f171870ad6be8ec820d2364e701feb8c7/debugpy-1.6.3-cp310-cp310-macosx_10_15_x86_64.whl", hash = "sha256:c4b2bd5c245eeb49824bf7e539f95fb17f9a756186e51c3e513e32999d8846f3"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/9b/ea/34e8e6cf32660d78eb6cbc538d086d543e9f44b27646d6faaac02380711f/debugpy-1.6.3-cp37-cp37m-win_amd64.whl", hash = "sha256:5ad571a36cec137ae6ed951d0ff75b5e092e9af6683da084753231150cbc5b25"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/ad/2a/eaeb7a147a7e978d3e8c591771058862edb18af69431039933d833bc3d33/debugpy-1.6.3-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:4e255982552b0edfe3a6264438dbd62d404baa6556a81a88f9420d3ed79b06ae"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/ae/9c/a3e68bab0a3b5395b623dec6b0d4caf2cbc8001e6943187873e1869e5a03/debugpy-1.6.3-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:adcfea5ea06d55d505375995e150c06445e2b20cd12885bcae566148c076636b"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/ce/8b/abf818eac48cf7c2b755e114768c80822c31a4815a4ccd4d8f89bbc2cbd3/debugpy-1.6.3-cp39-cp39-win32.whl", hash = "sha256:7c302095a81be0d5c19f6529b600bac971440db3e226dce85347cc27e6a61908"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/d2/e3/d0531ee73216d553d717bf4ac51dff297f89054619fa69db61eef028a07f/debugpy-1.6.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:daadab4403427abd090eccb38d8901afd8b393e01fd243048fab3f1d7132abb4"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/e4/d6/ed74635ad235293a77f65ccaa17ac3c6012839126f0512a5a53c7cbf82ff/debugpy-1.6.3-py2.py3-none-any.whl", hash = "sha256:84c39940a0cac410bf6aa4db00ba174f973eef521fbe9dd058e26bcabad89c4f"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/e4/fc/555a80da24d0608660f69aad6da45cce890f1b2d055d4d4cd6ed9cf0ea20/debugpy-1.6.3-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:c4cd6f37e3c168080d61d698390dfe2cd9e74ebf80b448069822a15dadcda57d"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/e5/f6/e594a128cd36870fa8e8e6fb6710b890a0074a582f5b19b483ee7b1c2193/debugpy-1.6.3-cp37-cp37m-win32.whl", hash = "sha256:3c9f985944a30cfc9ae4306ac6a27b9c31dba72ca943214dad4a0ab3840f6161"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/e6/b1/549746bbdd9b7b5a2ad96fcfde5553a8dfaf33034ef2c617fb50a5f19f3e/debugpy-1.6.3-cp310-cp310-win32.whl", hash = "sha256:fc233a0160f3b117b20216f1169e7211b83235e3cd6749bcdd8dbb72177030c7"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/e6/bb/614cfb27df644883e8db05dc4f47e9f3919303a8b125127933262a157847/debugpy-1.6.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:cca23cb6161ac89698d629d892520327dd1be9321c0960e610bbcb807232b45d"},
]
"decorator 5.1.1" = [
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/66/0c/8d907af351aa16b42caae42f9d6aa37b900c67308052d10fdce809f8d952/decorator-5.1.1.tar.gz", hash = "sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/d5/50/83c593b07763e1161326b3b8c6686f0f4b0f24d5526546bee538c89837d6/decorator-5.1.1-py3-none-any.whl", hash = "sha256:b8c3f85900b9dc423225913c5aace94729fe1fa9763b38939a95226f02d37186"},
]
"entrypoints 0.4" = [
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/35/a8/365059bbcd4572cbc41de17fd5b682be5868b218c3c5479071865cab9078/entrypoints-0.4-py3-none-any.whl", hash = "sha256:f174b5ff827504fd3cd97cc3f8649f3693f51538c7e4bdf3ef002c8429d42f9f"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/ea/8d/a7121ffe5f402dc015277d2d31eb82d2187334503a011c18f2e78ecbb9b2/entrypoints-0.4.tar.gz", hash = "sha256:b706eddaa9218a19ebcd67b56818f05bb27589b1ca9e8d797b74affad4ccacd4"},
]
"executing 0.10.0" = [
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/14/ab/82fbfcc5d1888770aeec5b7a17ad5ef0215ff3962c52a38f4429f7c9220b/executing-0.10.0-py2.py3-none-any.whl", hash = "sha256:9c745f80cda11eb22b62cbecf21156491a794eb56ab06f9d286a44e62822b24e"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/e3/a7/6380f9bc4367ea010de6297540f69433e9a6070b8b7c1f283ff250b48e60/executing-0.10.0.tar.gz", hash = "sha256:d1cd87c2e371e9966261410c5b3769d6df2f9e4a79a83eebd2662dd3388f9833"},
]
"h11 0.12.0" = [
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/60/0f/7a0eeea938eaf61074f29fed9717f2010e8d0e0905d36b38d3275a1e4622/h11-0.12.0-py3-none-any.whl", hash = "sha256:36a3cb8c0a032f56e2da7084577878a035d3b61d104230d4bd49c0c6b555a9c6"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/bd/e9/72c3dc8f7dd7874812be6a6ec788ba1300bfe31570963a7e788c86280cb9/h11-0.12.0.tar.gz", hash = "sha256:47222cb6067e4a307d535814917cd98fd0a57b6788ce715755fa2b6c28b56042"},
]
"httpcore 0.15.0" = [
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/42/98/44c3e51a0655eae75adefee028c9bada7427a90f63105e54f5e735946f50/httpcore-0.15.0.tar.gz", hash = "sha256:18b68ab86a3ccf3e7dc0f43598eaddcf472b602aba29f9aa6ab85fe2ada3980b"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/ad/b9/260603ca0913072a10a4367c2dca9998706812a8c1f4558eca510f85ae16/httpcore-0.15.0-py3-none-any.whl", hash = "sha256:1105b8b73c025f23ff7c36468e4432226cbb959176eab66864b8e31c4ee27fa6"},
]
"httpx 0.23.0" = [
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/43/cd/677173d194b4839e5b196709e3819ffca2a4bc58b0538f4ae4be877ad480/httpx-0.23.0.tar.gz", hash = "sha256:f28eac771ec9eb4866d3fb4ab65abd42d38c424739e80c08d8d20570de60b0ef"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/e9/fd/d8ff4bbf7ade1c9d60b53bf8234b44dcb2a9fcc7ae6933ae80ba38582f3e/httpx-0.23.0-py3-none-any.whl", hash = "sha256:42974f577483e1e932c3cdc3cd2303e883cbfba17fe228b0f63589764d7b9c4b"},
]
"idna 3.3" = [
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/04/a2/d918dcd22354d8958fe113e1a3630137e0fc8b44859ade3063982eacd2a4/idna-3.3-py3-none-any.whl", hash = "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/62/08/e3fc7c8161090f742f504f40b1bccbfc544d4a4e09eb774bf40aafce5436/idna-3.3.tar.gz", hash = "sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d"},
]
"ipykernel 6.15.1" = [
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/76/bb/54e9c5818c5a43ff05ef234821d530880f5cfeff3af4fc000a9c8a0ccc91/ipykernel-6.15.1.tar.gz", hash = "sha256:37acc3254caa8a0dafcddddc8dc863a60ad1b46487b68aee361d9a15bda98112"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/d4/41/73b1927cc2e6dd3e92ea2153772513ac00d65f7d9e29aabfdd4eee3512ce/ipykernel-6.15.1-py3-none-any.whl", hash = "sha256:d8969c5b23b0e453a23166da5a669c954db399789293fcb03fec5cb25367e43c"},
]
"ipython 8.4.0" = [
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/be/06/c0d9ff653f260fe4659b41d509f8e4d6e4bf1f07be594de2d7fd5979c688/ipython-8.4.0.tar.gz", hash = "sha256:f2db3a10254241d9b447232cec8b424847f338d9d36f9a577a6192c332a46abd"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/fe/10/0a5925e6e8e4c948b195b4c776cae0d9d7bc6382008a0f7ed2d293bf1cfb/ipython-8.4.0-py3-none-any.whl", hash = "sha256:7ca74052a38fa25fe9bedf52da0be7d3fdd2fb027c3b778ea78dfe8c212937d1"},
]
"isort 5.10.1" = [
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/ab/e9/964cb0b2eedd80c92f5172f1f8ae0443781a9d461c1372a3ce5762489593/isort-5.10.1.tar.gz", hash = "sha256:e8443a5e7a020e9d7f97f1d7d9cd17c88bcb3bc7e218bf9cf5095fe550be2951"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/b8/5b/f18e227df38b94b4ee30d2502fd531bebac23946a2497e5595067a561274/isort-5.10.1-py3-none-any.whl", hash = "sha256:6f62d78e2f89b4500b080fe3a81690850cd254227f27f75c3a0c491a1f351ba7"},
]
"jedi 0.18.1" = [
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/b3/0e/836f12ec50075161e365131f13f5758451645af75c2becf61c6351ecec39/jedi-0.18.1-py2.py3-none-any.whl", hash = "sha256:637c9635fcf47945ceb91cd7f320234a7be540ded6f3e99a50cb6febdfd1ba8d"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/c2/25/273288df952e07e3190446efbbb30b0e4871a0d63b4246475f3019d4f55e/jedi-0.18.1.tar.gz", hash = "sha256:74137626a64a99c8eb6ae5832d99b3bdd7d29a3850fe2aa80a4126b2a7d949ab"},
]
"jupyter-client 7.3.5" = [
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/35/af/66f66acacf1b22b1400cd46e1ac83810509511e7c75afbfbdd9155367a99/jupyter_client-7.3.5-py3-none-any.whl", hash = "sha256:b33222bdc9dd1714228bd286af006533a0abe2bbc093e8f3d29dc0b91bdc2be4"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/4d/d1/b6161a5e8639a0d35aeb59a50d944dc4928775db2408ea10b23087e354b6/jupyter_client-7.3.5.tar.gz", hash = "sha256:3c58466a1b8d55dba0bf3ce0834e4f5b7760baf98d1d73db0add6f19de9ecd1d"},
]
"jupyter-core 4.11.1" = [
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/66/5f/32ee101e07d5ece26876f13526b16179525e19f4e460f8085e9ef8e54cff/jupyter_core-4.11.1-py3-none-any.whl", hash = "sha256:715e22bb6cc7db3718fddfac1f69f1c7e899ca00e42bdfd4bf3705452b9fd84a"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/e4/e0/13fc7f8b72f39d87c1c32918a99475911b7b2f28c1a9f2734a5ab5cc35ef/jupyter_core-4.11.1.tar.gz", hash = "sha256:2e5f244d44894c4154d06aeae3419dd7f1b0ef4494dc5584929b398c61cfd314"},
]
"matplotlib-inline 0.1.6" = [
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/d9/50/3af8c0362f26108e54d58c7f38784a3bdae6b9a450bab48ee8482d737f44/matplotlib-inline-0.1.6.tar.gz", hash = "sha256:f887e5f10ba98e8d2b150ddcf4702c1e5f8b3a20005eb0f74bfdbd360ee6f304"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/f2/51/c34d7a1d528efaae3d8ddb18ef45a41f284eacf9e514523b191b7d0872cc/matplotlib_inline-0.1.6-py3-none-any.whl", hash = "sha256:f1f41aab5328aa5aaea9b16d083b128102f8712542f819fe7e6a420ff581b311"},
]
"mutagen 1.45.1" = [
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/16/b3/f7aa8edf2ff4495116f95fd442b2a346aa55d1d46313143c8814886dbcdb/mutagen-1.45.1-py3-none-any.whl", hash = "sha256:9c9f243fcec7f410f138cb12c21c84c64fde4195481a30c9bfb05b5f003adfed"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/f3/d9/2232a4cb9a98e2d2501f7e58d193bc49c956ef23756d7423ba1bd87e386d/mutagen-1.45.1.tar.gz", hash = "sha256:6397602efb3c2d7baebd2166ed85731ae1c1d475abca22090b7141ff5034b3e1"},
]
"mypy-extensions 0.4.3" = [
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/5c/eb/975c7c080f3223a5cdaff09612f3a5221e4ba534f7039db34c35d95fa6a5/mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/63/60/0582ce2eaced55f65a4406fc97beba256de4b7a95a0034c6576458c6519f/mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"},
]
"nest-asyncio 1.5.5" = [
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/7b/19/efddf713ba62f738d2bf410a6f5ead6e621f9354d5824091ce8b7a233e11/nest_asyncio-1.5.5.tar.gz", hash = "sha256:e442291cd942698be619823a17a86a5759eabe1f8613084790de189fe9e16d65"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/be/1e/a83058de46b40a392bdefcaac44d1d42db4bf8562cb68c95d6bae4b93276/nest_asyncio-1.5.5-py3-none-any.whl", hash = "sha256:b98e3ec1b246135e4642eceffa5a6c23a3ab12c82ff816a92c612d68205813b2"},
]
"packaging 21.3" = [
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/05/8e/8de486cbd03baba4deef4142bd643a3e7bbe954a784dc1bb17142572d127/packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/df/9e/d1a7217f69310c1db8fdf8ab396229f55a699ce34a203691794c5d1cad0c/packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"},
]
"parso 0.8.3" = [
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/05/63/8011bd08a4111858f79d2b09aad86638490d62fbf881c44e434a6dfca87b/parso-0.8.3-py2.py3-none-any.whl", hash = "sha256:c001d4636cd3aecdaf33cbb40aebb59b094be2a74c556778ef5576c175e19e75"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/a2/0e/41f0cca4b85a6ea74d66d2226a7cda8e41206a624f5b330b958ef48e2e52/parso-0.8.3.tar.gz", hash = "sha256:8c07be290bb59f03588915921e29e8a50002acaf2cdc5fa0e0114f91709fafa0"},
]
"pathspec 0.9.0" = [
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/42/ba/a9d64c7bcbc7e3e8e5f93a52721b377e994c22d16196e2b0f1236774353a/pathspec-0.9.0-py2.py3-none-any.whl", hash = "sha256:7d15c4ddb0b5c802d161efc417ec1a2558ea2653c2e8ad9c19098201dc1c993a"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/f6/33/436c5cb94e9f8902e59d1d544eb298b83c84b9ec37b5b769c5a0ad6edb19/pathspec-0.9.0.tar.gz", hash = "sha256:e564499435a2673d586f6b2130bb5b95f04a3ba06f81b8f895b651a3c76aabb1"},
]
"pexpect 4.8.0" = [
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/39/7b/88dbb785881c28a102619d46423cb853b46dbccc70d3ac362d99773a78ce/pexpect-4.8.0-py2.py3-none-any.whl", hash = "sha256:0b48a55dcb3c05f3329815901ea4fc1537514d6ba867a152b581d69ae3710937"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/e5/9b/ff402e0e930e70467a7178abb7c128709a30dfb22d8777c043e501bc1b10/pexpect-4.8.0.tar.gz", hash = "sha256:fc65a43959d153d0114afe13997d439c22823a27cefceb5ff35c2178c6784c0c"},
]
"pickleshare 0.7.5" = [
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/9a/41/220f49aaea88bc6fa6cba8d05ecf24676326156c23b991e80b3f2fc24c77/pickleshare-0.7.5-py2.py3-none-any.whl", hash = "sha256:9649af414d74d4df115d5d718f82acb59c9d418196b7b4290ed47a12ce62df56"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/d8/b6/df3c1c9b616e9c0edbc4fbab6ddd09df9535849c64ba51fcb6531c32d4d8/pickleshare-0.7.5.tar.gz", hash = "sha256:87683d47965c1da65cdacaf31c8441d12b8044cdec9aca500cd78fc2c683afca"},
]
"platformdirs 2.5.2" = [
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/ed/22/967181c94c3a4063fe64e15331b4cb366bdd7dfbf46fcb8ad89650026fec/platformdirs-2.5.2-py3-none-any.whl", hash = "sha256:027d8e83a2d7de06bbac4e5ef7e023c02b863d7ea5d079477e722bb41ab25788"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/ff/7b/3613df51e6afbf2306fc2465671c03390229b55e3ef3ab9dd3f846a53be6/platformdirs-2.5.2.tar.gz", hash = "sha256:58c8abb07dcb441e6ee4b11d8df0ac856038f944ab98b7be6b27b2a3c7feef19"},
]
"prompt-toolkit 3.0.30" = [
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/b0/8f/09a88160539a1164de562809f8b1d0a36dc1f9d8c6473f4b71ebed17b953/prompt_toolkit-3.0.30-py3-none-any.whl", hash = "sha256:d8916d3f62a7b67ab353a952ce4ced6a1d2587dfe9ef8ebc30dd7c386751f289"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/c5/7e/71693dc21d20464e4cd7c600f2d8fad1159601a42ed55566500272fe69b5/prompt_toolkit-3.0.30.tar.gz", hash = "sha256:859b283c50bde45f5f97829f77a4674d1c1fcd88539364f1b28a37805cfd89c0"},
]
"psutil 5.9.1" = [
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/13/71/c25adbd9b33a2e27edbe1fc84b3111a5ad97611885d7abcbdd8d1f2bb7ca/psutil-5.9.1-cp37-cp37m-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3054e923204b8e9c23a55b23b6df73a8089ae1d075cb0bf711d3e9da1724ded4"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/14/06/39d7e963a6a8bbf26519de208593cdb0ddfe22918b8989f4b2363d4ab49f/psutil-5.9.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:abd9246e4cdd5b554a2ddd97c157e292ac11ef3e7af25ac56b08b455c829dca8"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/1b/53/8f0772df0a6d593bc2fcdf12f4f790bab5c4f6a77bb61a8ddaad2cbba7f8/psutil-5.9.1-cp27-cp27m-win_amd64.whl", hash = "sha256:e7e10454cb1ab62cc6ce776e1c135a64045a11ec4c6d254d3f7689c16eb3efd2"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/26/b4/a58cf15ea649faa92c54f00c627aef1d50b9f1abf207485f10c967a50c95/psutil-5.9.1-cp310-cp310-win32.whl", hash = "sha256:20b27771b077dcaa0de1de3ad52d22538fe101f9946d6dc7869e6f694f079329"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/2a/32/136cd5bf55728ea64a22b1d817890e35fc17314c46a24ee3268b65f9076f/psutil-5.9.1-cp37-cp37m-win32.whl", hash = "sha256:d2d006286fbcb60f0b391741f520862e9b69f4019b4d738a2a45728c7e952f1b"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/2c/9d/dc329b7da284677ea843f3ff4b35b8ab3b96b65a58a544b3c3f86d9d032f/psutil-5.9.1-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:44d1826150d49ffd62035785a9e2c56afcea66e55b43b8b630d7706276e87f22"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/2d/56/54b4ed8102ce5a2f5367b4e766c1873c18f9c32cde321435d0e0ee2abcc5/psutil-5.9.1-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:56960b9e8edcca1456f8c86a196f0c3d8e3e361320071c93378d41445ffd28b0"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/41/ec/5fd3e9388d0ed1edfdeae71799df374f4a117932646a63413fa95a121e9f/psutil-5.9.1-cp38-cp38-win32.whl", hash = "sha256:a8746bfe4e8f659528c5c7e9af5090c5a7d252f32b2e859c584ef7d8efb1e689"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/46/80/1de3a9bac336b5c8e4f7b0ff2e80c85ba237f18f2703be68884ee6798432/psutil-5.9.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:19f36c16012ba9cfc742604df189f2f28d2720e23ff7d1e81602dbe066be9fd1"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/62/1f/f14225bda76417ab9bd808ff21d5cd59d5435a9796ca09b34d4cb0edcd88/psutil-5.9.1-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:645bd4f7bb5b8633803e0b6746ff1628724668681a434482546887d22c7a9537"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/65/1d/6a112f146faee6292a6c3ee2a7f24a8e572697adb7e1c5de3d8508f647cc/psutil-5.9.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:3a76ad658641172d9c6e593de6fe248ddde825b5866464c3b2ee26c35da9d237"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/6b/76/a8cb69ed3566877dcbccf408f5f9d6055227ad4fed694e88809fa8506b0b/psutil-5.9.1-cp36-cp36m-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:068935df39055bf27a29824b95c801c7a5130f118b806eee663cad28dca97685"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/6d/c6/6a4e46802e8690d50ba6a56c7f79ac283e703fcfa0fdae8e41909c8cef1f/psutil-5.9.1-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:29a442e25fab1f4d05e2655bb1b8ab6887981838d22effa2396d584b740194de"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/73/1a/d78f2f2de2aad6628415d2a48917cabc2c7fb0c3a31c7cdf187cffa4eb36/psutil-5.9.1-cp36-cp36m-win_amd64.whl", hash = "sha256:db417f0865f90bdc07fa30e1aadc69b6f4cad7f86324b02aa842034efe8d8c4d"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/77/06/f9fd79449440d7217d6bf2c90998d540e125cfeffe39d214a328dadc46f4/psutil-5.9.1-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:799759d809c31aab5fe4579e50addf84565e71c1dc9f1c31258f159ff70d3f87"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/7e/52/a02dc53e26714a339c8b4972d8e3f268e4db8905f5d1a3a100f1e40b6fa7/psutil-5.9.1-cp36-cp36m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a6a11e48cb93a5fa606306493f439b4aa7c56cb03fc9ace7f6bfa21aaf07c453"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/7e/8d/e0a66123fa98e309597815de518b47a7a6c571a8f886fc8d4db2331fd2ab/psutil-5.9.1-cp27-cp27m-win32.whl", hash = "sha256:0904727e0b0a038830b019551cf3204dd48ef5c6868adc776e06e93d615fc5fc"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/85/4d/78173e3dffb74c5fa87914908f143473d0b8b9183f9d275333679a4e4649/psutil-5.9.1-cp36-cp36m-win32.whl", hash = "sha256:0f15a19a05f39a09327345bc279c1ba4a8cfb0172cc0d3c7f7d16c813b2e7d36"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/97/f6/0180e58dd1359da7d6fbc27d04dac6fb500dc758b6f4b65407608bb13170/psutil-5.9.1-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fea896b54f3a4ae6f790ac1d017101252c93f6fe075d0e7571543510f11d2676"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/9d/41/d5f2db2ab7f5dff2fa795993a0cd6fa8a8f39ca197c3a86857875333ec10/psutil-5.9.1-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4b6750a73a9c4a4e689490ccb862d53c7b976a2a35c4e1846d049dcc3f17d83b"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/9f/ca/84ce3e48b3ca2f0f74314d89929b3a523220f3f4a8dff395d6ef74dadef3/psutil-5.9.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:28976df6c64ddd6320d281128817f32c29b539a52bdae5e192537bc338a9ec81"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/a9/97/b7e3532d97d527349701d2143c3f868733b94e2db6f531b07811b698f549/psutil-5.9.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b88f75005586131276634027f4219d06e0561292be8bd6bc7f2f00bdabd63c4e"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/b1/d2/c5374a784567c1e42ee8a589b1b42e2bd6e14c7be3c234d84360ab3a0a39/psutil-5.9.1-cp39-cp39-win32.whl", hash = "sha256:32c52611756096ae91f5d1499fe6c53b86f4a9ada147ee42db4991ba1520e574"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/b2/ad/65e2b2b97677f98d718388dc11b2a9d7f177ebbae5eef72547a32bc28911/psutil-5.9.1-cp38-cp38-win_amd64.whl", hash = "sha256:79c9108d9aa7fa6fba6e668b61b82facc067a6b81517cab34d07a84aa89f3df0"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/c0/5a/2ac88d5265b711c8aa4e786825b38d5d0b1e5ecbdd0ce78e9b04a820d247/psutil-5.9.1-cp310-cp310-win_amd64.whl", hash = "sha256:58678bbadae12e0db55186dc58f2888839228ac9f41cc7848853539b70490021"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/cf/29/ad704a45960bfb52ef8bf0beb9c41c09ce92d61c40333f03e9a03f246c22/psutil-5.9.1-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:9272167b5f5fbfe16945be3db475b3ce8d792386907e673a209da686176552af"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/d1/16/6239e76ab5d990dc7866bc22a80585f73421588d63b42884d607f5f815e2/psutil-5.9.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c7be9d7f5b0d206f0bbc3794b8e16fb7dbc53ec9e40bbe8787c6f2d38efcf6c9"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/d6/de/0999ea2562b96d7165812606b18f7169307b60cd378bc29cf3673322c7e9/psutil-5.9.1.tar.gz", hash = "sha256:57f1819b5d9e95cdfb0c881a8a5b7d542ed0b7c522d575706a80bedc848c8954"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/d6/ef/fd4dc9085e3879c3af63fe60667dd3b71adf50d030b5549315f4a619271b/psutil-5.9.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:91c7ff2a40c373d0cc9121d54bc5f31c4fa09c346528e6a08d1845bce5771ffc"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/df/88/427f3959855fcb3ab04891e00c026a246892feb11b20433db814b7a24405/psutil-5.9.1-cp37-cp37m-win_amd64.whl", hash = "sha256:b14ee12da9338f5e5b3a3ef7ca58b3cba30f5b66f7662159762932e6d0b8f680"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/e0/ac/fd6f098969d49f046083ac032e6788d9f861903596fb9555a02bf50a1238/psutil-5.9.1-cp39-cp39-win_amd64.whl", hash = "sha256:f65f9a46d984b8cd9b3750c2bdb419b2996895b005aefa6cbaba9a143b1ce2c5"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/fd/ba/c5a3f46f351ab609cc0be6a563e492900c57e3d5c9bda0b79b84d8c3eae9/psutil-5.9.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:944c4b4b82dc4a1b805329c980f270f170fdc9945464223f2ec8e57563139cf4"},
]
"ptyprocess 0.7.0" = [
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/20/e5/16ff212c1e452235a90aeb09066144d0c5a6a8c0834397e03f5224495c4e/ptyprocess-0.7.0.tar.gz", hash = "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/22/a6/858897256d0deac81a172289110f31629fc4cee19b6f01283303e18c8db3/ptyprocess-0.7.0-py2.py3-none-any.whl", hash = "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35"},
]
"pure-eval 0.2.2" = [
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/2b/27/77f9d5684e6bce929f5cfe18d6cfbe5133013c06cb2fbf5933670e60761d/pure_eval-0.2.2-py3-none-any.whl", hash = "sha256:01eaab343580944bc56080ebe0a674b39ec44a945e6d09ba7db3cb8cec289350"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/97/5a/0bc937c25d3ce4e0a74335222aee05455d6afa2888032185f8ab50cdf6fd/pure_eval-0.2.2.tar.gz", hash = "sha256:2b45320af6dfaa1750f543d714b6d1c520a1688dec6fd24d339063ce0aaa9ac3"},
]
"py 1.11.0" = [
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/98/ff/fec109ceb715d2a6b4c4a85a61af3b40c723a961e8828319fbcb15b868dc/py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/f6/f0/10642828a8dfb741e5f3fbaac830550a518a775c7fff6f04a007259b0548/py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"},
]
"pycparser 2.21" = [
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/5e/0b/95d387f5f4433cb0f53ff7ad859bd2c6051051cebbb564f139a999ab46de/pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/62/d5/5f610ebe421e85889f2e55e33b7f9a6795bd982198517d912eb1c76e1a53/pycparser-2.21-py2.py3-none-any.whl", hash = "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9"},
]
"pydantic 1.9.2" = [
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/04/bc/5231387df42b199f38dd3f29eb10338bc0a272e24020aff5c4cd64d3270d/pydantic-1.9.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7ead3cd020d526f75b4188e0a8d71c0dbbe1b4b6b5dc0ea775a93aca16256aeb"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/18/2f/228fe5d1dbf7c36bd252fb304b015d02a50f696e659a0bb370a5628d00f4/pydantic-1.9.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:bd67cb2c2d9602ad159389c29e4ca964b86fa2f35c2faef54c3eb28b4efd36c8"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/36/23/e7609029b3a71c95613e132e8abcfae2bff2da0aa6d894bad2f0048a3895/pydantic-1.9.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9c9e04a6cdb7a363d7cb3ccf0efea51e0abb48e180c0d31dca8d247967d85c6e"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/4c/f3/b8e7c5b68515f6c0c881b0cd64c03b17e6bc3005b0193be6485c0d5f98f0/pydantic-1.9.2-cp38-cp38-win_amd64.whl", hash = "sha256:d70916235d478404a3fa8c997b003b5f33aeac4686ac1baa767234a0f8ac2326"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/52/e2/52961699414260e6b55500600c90acad94861c981f6ebfdb12e5e99ad1d4/pydantic-1.9.2-cp36-cp36m-win_amd64.whl", hash = "sha256:84d76ecc908d917f4684b354a39fd885d69dd0491be175f3465fe4b59811c001"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/5c/3c/c9ba5be133267efad3be3d46d8b76a1d3c0458feb13838154805803513fb/pydantic-1.9.2-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e0b214e57623a535936005797567231a12d0da0c29711eb3514bc2b3cd008d0f"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/60/ed/40e339ee852bf1e261b24f1917e6ad6814d488ee23bff91f9e275bfe58e5/pydantic-1.9.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fafe841be1103f340a24977f61dee76172e4ae5f647ab9e7fd1e1fca51524f08"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/6f/1e/4dca34af2a7e8effb5226ac2fec3664e99c8e95c97e8ebae9ff47fb3bbef/pydantic-1.9.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f0ca86b525264daa5f6b192f216a0d1e860b7383e3da1c65a1908f9c02f42801"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/75/44/e3c3c72ddbf7f6c987e39cc09f21f61f21cffeebddb75b9019f952624942/pydantic-1.9.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a8c5360a0297a713b4123608a7909e6869e1b56d0e96eb0d792c27585d40757f"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/83/cb/2781906491a09eb7c81e78638624dc4a3dd30c36b6a4bf33221f83609c4d/pydantic-1.9.2-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:b34ba24f3e2d0b39b43f0ca62008f7ba962cff51efa56e64ee25c4af6eed987b"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/84/cf/b2514b857196fb8484209c6bf365a164b684f6eef3d1feaa4f9ce2447389/pydantic-1.9.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:e631c70c9280e3129f071635b81207cad85e6c08e253539467e4ead0e5b219aa"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/85/15/fc8232045224fbc566c2e5f618f17519eb2ae8f15e9e63d6f3363ece7421/pydantic-1.9.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afacf6d2a41ed91fc631bade88b1d319c51ab5418870802cedb590b709c5ae3c"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/86/f8/c2effc693180e16b3ec886bc9d080f937afa7964823a7c204d5c9df55264/pydantic-1.9.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:91089b2e281713f3893cd01d8e576771cd5bfdfbff5d0ed95969f47ef6d676c3"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/88/83/42a71762ec2f127ba8141a0608dea0ee2a8aa2dd6fcc0d2cda375aee61eb/pydantic-1.9.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e78578f0c7481c850d1c969aca9a65405887003484d24f6110458fb02cca7747"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/95/5b/5d1d8d5e6e2d9a1ec3a94b75b14fe5a2e6efd13fa96a3e53144db9de9d48/pydantic-1.9.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:4de71c718c9756d679420c69f216776c2e977459f77e8f679a4a961dc7304a56"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/a0/cb/672a6e3a9fa78c9a21f274dbdef7f20633969527f07ac8f882263844f4c1/pydantic-1.9.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5803ad846cdd1ed0d97eb00292b870c29c1f03732a010e66908ff48a762f20e4"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/a1/ef/b9cc1565084701825f4b21ef87bc965025cf5b80b2cb647e668accab1602/pydantic-1.9.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3ee0d69b2a5b341fc7927e92cae7ddcfd95e624dfc4870b32a85568bd65e6131"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/aa/c9/0447b23ca481a0222ab0f75bd660ab0035db2c47554825778afb0e92938e/pydantic-1.9.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:328558c9f2eed77bd8fffad3cef39dbbe3edc7044517f4625a769d45d4cf7555"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/ac/bf/9ff92dc00d2dae537c453220e5bab6f5b18ff0f4f1bbe65e12af1b857a5c/pydantic-1.9.2-cp39-cp39-win_amd64.whl", hash = "sha256:f1a68f4f65a9ee64b6ccccb5bf7e17db07caebd2730109cb8a95863cfa9c4e55"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/bb/9c/7ded003135342ea07fcac5581790634a2d70340175c1e7cb2f0affcb1962/pydantic-1.9.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1061c6ee6204f4f5a27133126854948e3b3d51fcc16ead2e5d04378c199b2f44"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/bb/e4/e77fe8e16ce33f2737a0fbe9e3566eb05ac141079e6cac9b0d7835e5b778/pydantic-1.9.2-cp37-cp37m-win_amd64.whl", hash = "sha256:32e0b4fb13ad4db4058a7c3c80e2569adbd810c25e6ca3bbd8b2a9cc2cc871d7"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/be/72/841dcb62c23d8955b82784dd3bb73770d1ce8aa562e5bd47c1f52230ca12/pydantic-1.9.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5565a49effe38d51882cb7bac18bda013cdb34d80ac336428e8908f0b72499b0"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/c2/6e/f4d724c7004cace580bd3c7ee6be87f4607dda0249574235d26d19b4258c/pydantic-1.9.2-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bd446bdb7755c3a94e56d7bdfd3ee92396070efa8ef3a34fab9579fe6aa1d84"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/ca/e3/4083d8f5d6691d677be9a99d53a66da3cbecc91cafc6c48d08c75490b3ba/pydantic-1.9.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:ff68fc85355532ea77559ede81f35fff79a6a5543477e168ab3a381887caea76"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/d3/4b/6f539c1f26c6a8ed942fa751981909ab86336ce5ead28b6c92590ee6bc1b/pydantic-1.9.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:4aafd4e55e8ad5bd1b19572ea2df546ccace7945853832bb99422a79c70ce9b8"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/dd/1c/0046af6bfd47982495b502400e90ffdee0b5e4af11be4e58b50d47007f27/pydantic-1.9.2-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:d8ce3fb0841763a89322ea0432f1f59a2d3feae07a63ea2c958b2315e1ae8adb"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/e0/0f/a8adcc49e58994f6da6b96dac42dedbedd250c3130d59a664d8130c8019d/pydantic-1.9.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:cdb4272678db803ddf94caa4f94f8672e9a46bae4a44f167095e4d06fec12979"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/e6/b7/e50089199de9952f7156b8931c2bcd3db6654845d6c453046e9073a5f56d/pydantic-1.9.2-cp310-cp310-win_amd64.whl", hash = "sha256:615661bfc37e82ac677543704437ff737418e4ea04bef9cf11c6d27346606044"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/e9/64/3395d45a05adcebb6d1025702c28d1ed188703397f38999295c52687f87e/pydantic-1.9.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5da164119602212a3fe7e3bc08911a89db4710ae51444b4224c2382fd09ad453"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/ed/c9/ffe44727dadb0930783a1ffb60facf8ead7dffbb67db9ae2fa28dacabcf1/pydantic-1.9.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:19b5686387ea0d1ea52ecc4cffb71abb21702c5e5b2ac626fd4dbaa0834aa49d"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/f6/63/b412252dbbdc712500ad73fe2e591c3220781e63a8c135d26b7d60fcb99c/pydantic-1.9.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4b3946f87e5cef3ba2e7bd3a4eb5a20385fe36521d6cc1ebf3c08a6697c6cfb3"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/f7/76/4a98738c31e520c78a80e9575b655b5c3ae96313102478bff4d643abc2e9/pydantic-1.9.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:7d0f183b305629765910eaad707800d2f47c6ac5bcfb8c6397abdc30b69eeb15"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/f7/ea/05d5fa5ab16536524258c73e932e2c417e47fffa33a939bf7c12e956b961/pydantic-1.9.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c0f5e142ef8217019e3eef6ae1b6b55f09a7a15972958d44fbd228214cede567"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/fd/8f/3f7e88b507dbdfec8f1f914294aa8831edffb03d668799c65b4b46331c8a/pydantic-1.9.2.tar.gz", hash = "sha256:8cb0bc509bfb71305d7a59d00163d5f9fc4530f0881ea32c74ff4f74c85f3d3d"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/fe/27/0de772dcd0517770b265dbc3998ed3ee3aa2ba25ba67e3685116cbbbccc6/pydantic-1.9.2-py3-none-any.whl", hash = "sha256:78a4d6bdfd116a559aeec9a4cfe77dda62acc6233f8b56a716edad2651023e5e"},
]
"pygments 2.13.0" = [
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/4f/82/672cd382e5b39ab1cd422a672382f08a1fb3d08d9e0c0f3707f33a52063b/Pygments-2.13.0-py3-none-any.whl", hash = "sha256:f643f331ab57ba3c9d89212ee4a2dabc6e94f117cf4eefde99a0574720d14c42"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/e0/ef/5905cd3642f2337d44143529c941cc3a02e5af16f0f65f81cbef7af452bb/Pygments-2.13.0.tar.gz", hash = "sha256:56a8508ae95f98e2b9bdf93a6be5ae3f7d8af858b43e02c5a2ff083726be40c1"},
]
"pyparsing 3.0.9" = [
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/6c/10/a7d0fa5baea8fe7b50f448ab742f26f52b80bfca85ac2be9d35cdd9a3246/pyparsing-3.0.9-py3-none-any.whl", hash = "sha256:5026bae9a10eeaefb61dab2f09052b9f4307d44aee4eda64b309723d8d206bbc"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/71/22/207523d16464c40a0310d2d4d8926daffa00ac1f5b1576170a32db749636/pyparsing-3.0.9.tar.gz", hash = "sha256:2b020ecf7d21b687f219b71ecad3631f644a47f01403fa1d1036b0c6416d70fb"},
]
"python-dateutil 2.8.2" = [
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/36/7a/87837f39d0296e723bb9b62bbb257d0355c7f6128853c78955f57342a56d/python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/4c/c4/13b4776ea2d76c115c1d1b84579f3764ee6d57204f6be27119f13a61d0a9/python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"},
]
"pywin32 304" = [
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/05/6b/9f8421a9a2ab5f33cbb9fd2f282ac971e584f6a83d44f6672bd17f1d68b2/pywin32-304-cp310-cp310-win32.whl", hash = "sha256:3c7bacf5e24298c86314f03fa20e16558a4e4138fc34615d7de4070c23e65af3"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/14/07/9a2bd2cdcdeecd013ed83173209f1c984662ef05922ef6fe5f0fb9cc120e/pywin32-304-cp310-cp310-win_amd64.whl", hash = "sha256:4f32145913a2447736dad62495199a8e280a77a0ca662daa2332acf849f0be48"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/38/48/9a480ef4bba85a6318d1d7572346d315fbed5472f297d3f3d56ed0a428ea/pywin32-304-cp39-cp39-win32.whl", hash = "sha256:25746d841201fd9f96b648a248f731c1dec851c9a08b8e33da8b56148e4c65cc"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/39/c0/cd6cb7bd1619f647b1614cf622190e4ff089c21032c219da9a7ae3c1de6d/pywin32-304-cp311-cp311-win_arm64.whl", hash = "sha256:cbbe34dad39bdbaa2889a424d28752f1b4971939b14b1bb48cbf0182a3bcfc43"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/4d/33/251aacef6d983476e4176e3c9b542f60c34735c034392e73762e699e9a5c/pywin32-304-cp38-cp38-win_amd64.whl", hash = "sha256:ead865a2e179b30fb717831f73cf4373401fc62fbc3455a0889a7ddac848f83e"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/6b/9e/44c8b74afb6657e1ca48b4855fcdebad29ae4ead654d88238bea319ec993/pywin32-304-cp311-cp311-win_amd64.whl", hash = "sha256:7ffa0c0fa4ae4077e8b8aa73800540ef8c24530057768c3ac57c609f99a14fd4"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/70/94/44ec60e63d77fb3bb9ff91e6906baf3e750445dc8b6b8374d1c6d79c9412/pywin32-304-cp36-cp36m-win_amd64.whl", hash = "sha256:de9827c23321dcf43d2f288f09f3b6d772fee11e809015bdae9e69fe13213988"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/75/91/fa2a9d3861184df4c2dc57c9a29e6e856f6bbe3702acccf169329f9b6eae/pywin32-304-cp310-cp310-win_arm64.whl", hash = "sha256:d3ee45adff48e0551d1aa60d2ec066fec006083b791f5c3527c40cd8aefac71f"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/a4/d9/e80172360b380ea41f423f3ddf2d0d986dd88c7b69c102494f52fd84012f/pywin32-304-cp37-cp37m-win_amd64.whl", hash = "sha256:bb2ea2aa81e96eee6a6b79d87e1d1648d3f8b87f9a64499e0b92b30d141e76df"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/bc/ca/9311427c719f6902c30ac4a6b252a38632fa3fd0e7b360a526a0a3b1dae7/pywin32-304-cp39-cp39-win_amd64.whl", hash = "sha256:d24a3382f013b21aa24a5cfbfad5a2cd9926610c0affde3e8ab5b3d7dbcf4ac9"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/c1/8b/dde940428f9b891e1d9d7b0c2199c7a332d57429ae49e10e1619d67044db/pywin32-304-cp36-cp36m-win32.whl", hash = "sha256:be253e7b14bc601718f014d2832e4c18a5b023cbe72db826da63df76b77507a1"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/cd/6e/430881ffd1902a4c7a0eaed73a2a9469625a8f25eb223efa443d1158321d/pywin32-304-cp38-cp38-win32.whl", hash = "sha256:94037b5259701988954931333aafd39cf897e990852115656b014ce72e052e96"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/dd/1a/3fabb07100936c52ec063e4de01ecfbdef7120704f15277b3565cc2f461f/pywin32-304-cp311-cp311-win32.whl", hash = "sha256:30c53d6ce44c12a316a06c153ea74152d3b1342610f1b99d40ba2795e5af0269"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/ee/88/35150e6f5abce37693525c05176f55efed4996c997e88e4a31746e53d638/pywin32-304-cp37-cp37m-win32.whl", hash = "sha256:f64c0377cf01b61bd5e76c25e1480ca8ab3b73f0c4add50538d332afdf8f69c5"},
]
"pyzmq 23.2.1" = [
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/10/3a/3de30981a94daf2b5d3406f33a377f4abf84ea341f3b1e8089300dadabca/pyzmq-23.2.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ffc6b1623d0f9affb351db4ca61f432dca3628a5ee015f9bf2bfbe9c6836881c"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/16/fa/b2cace8b458cae06f71da23eb88f04ce8bf357fe15149a958c81dd90aa3b/pyzmq-23.2.1-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:9269fbfe3a4eb2009199120861c4571ef1655fdf6951c3e7f233567c94e8c602"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/29/b5/af6c9deca82bdcbe88d01c2deb7a38bb10df06c14b9427339bdc301936e3/pyzmq-23.2.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:022cf5ea7bcaa8a06a03c2706e0ae66904b6138b2155577cd34c64bc7cc637ab"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/2b/fd/6859a0b96a9b6c652d442204c477cea246c2cc419d03fd6d39f4c4983651/pyzmq-23.2.1-cp39-cp39-macosx_10_15_universal2.whl", hash = "sha256:99a5a77a10863493a1ee8dece02578c6b32025fb3afff91b40476bc489e81648"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/2d/30/6e59d809233e4b0944b6aa1445e27b88d9f93ed473ec3cb9ae22689220a2/pyzmq-23.2.1-cp36-cp36m-win_amd64.whl", hash = "sha256:1f368a82b29f80071781b20663c0fc0c8f6b13273f9f5abe1526af939534f90f"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/2f/6d/b22db88efd23a40cc6f61315aa8d007d984b05bbe4a47aedfec31b8dcfa0/pyzmq-23.2.1-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:07ed8aaf7ffe150af873269690cc654ffeca7491f62aae0f3821baa181f8d5fe"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/34/a8/205ff0d87f3ace368fd44f42916b7d4cd3a181f074cf12e97be9bad67eea/pyzmq-23.2.1-cp38-cp38-win32.whl", hash = "sha256:28dbdb90b2f6b131f8f10e6081012e4e25234213433420e67e0c1162de537113"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/35/3d/22e9c618943d2d8c6e5c2885378abcbd44171a617f809f6a0d8f853565cc/pyzmq-23.2.1-cp37-cp37m-win_amd64.whl", hash = "sha256:9e5bf6e7239fc9687239de7a283aa8b801ab85371116045b33ae20132a1325d6"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/38/4f/c6e7867789dcd421533c7916789160122cc5327bea5f566c0f2064c4ba5e/pyzmq-23.2.1-cp38-cp38-win_amd64.whl", hash = "sha256:10d1910ec381b851aeb024a042a13db178cb1edf125e76a4e9d2548ad103aadb"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/38/e7/3ff3068074316da9990e889382b7a5f08728ebca893a2b8e018c1531633f/pyzmq-23.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f07016e3cf088dbfc6e7c5a7b3f540db5c23b0190d539e4fd3e2b5e6beffa4b5"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/3a/eb/386012ea557d752a88a9268ddab46f1fc2e8343e3fe50b396a89b63b2b2c/pyzmq-23.2.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:385609812eafd9970c3752c51f2f6c4f224807e3e441bcfd8c8273877d00c8a8"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/43/51/264ff1ee810c4a5b53b47ebc0cc68ac9a5c5e14bae60da48a17533e017bf/pyzmq-23.2.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6fd5d0d50cbcf4bc376861529a907bed026a4cbe8c22a500ff8243231ef02433"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/44/cd/936c1d0ff6427e5502bb56f679c548bff5a8a72f7e2db3e75a8b4682d2c5/pyzmq-23.2.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:b815991c7d024bf461f358ad871f2be1135576274caed5749c4828859e40354e"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/4a/3c/9e4b7e6675774eddcea834916f95fc16a115bcd138ce4fc6acddf8527d48/pyzmq-23.2.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:044447ae4b2016a6b8697571fd633f799f860b19b76c4a2fd9b1140d52ee6745"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/4d/a8/cebfae44f2243723ae18707f0eaef821d5ddba80b106c21060e8d7f08385/pyzmq-23.2.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:23e708fbfdf4ee3107422b69ca65da1b9f056b431fc0888096a8c1d6cd908e8f"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/4d/b4/804256cc2a3668b152c5ddf65bf319ae8d922ef6bfadee24e0ef23f096d6/pyzmq-23.2.1-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:84678153432241bcdca2210cf4ff83560b200556867aea913ffbb960f5d5f340"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/5b/74/e7470d011fde823298956ef1b8d28d04453061e3f284521989f84adad6e5/pyzmq-23.2.1-cp39-cp39-win32.whl", hash = "sha256:342ca3077f47ec2ee41b9825142b614e03e026347167cbc72a59b618c4f6106c"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/5b/e3/79b5a8bac06abda794ce1a5721ec9cfb8e058b3ca3d30174a10a628c1ea4/pyzmq-23.2.1-pp38-pypy38_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:d904f6595acfaaf99a1a61881fea068500c40374d263e5e073aa4005e5f9c28a"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/5c/46/81a9e4fc3d877efa6ed0d3bd2c4c4b351860169a719d2f3508fd789e3c33/pyzmq-23.2.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6b1e79bba24f6df1712e3188d5c32c480d8eda03e8ecff44dc8ecb0805fa62f3"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/5d/d6/48df9759cbc60d482481e9fa51b04f5759f822c4ad7e576224701bdf25a4/pyzmq-23.2.1-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:624fd38071a817644acdae075b92a23ea0bdd126a58148288e8284d23ec361ce"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/61/0f/351e943dcab89e1a4d21f3531ba7ffd7142aac5148cb762a022b1c9e8844/pyzmq-23.2.1-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:2f67b63f53c6994d601404fd1a329e6d940ac3dd1d92946a93b2b9c70df67b9f"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/61/d9/2f1ebd8e0583a008cdd7c246c13effd0a469a91690d64f1184bb2e0ad18d/pyzmq-23.2.1-cp310-cp310-win32.whl", hash = "sha256:e1fe30bcd5aea5948c42685fad910cd285eacb2518ea4dc6c170d6b535bee95d"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/64/fc/9ea90ccf7ad0685695732158b2ec984dd7c90183bbe3c187ee1135eb9128/pyzmq-23.2.1-cp37-cp37m-win32.whl", hash = "sha256:8a68f57b7a3f7b6b52ada79876be1efb97c8c0952423436e84d70cc139f16f0d"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/6a/d7/404271dc05bb88f7cfc97dcdfe55bc2fbec268e9c2cf4ec5c0609ecc118d/pyzmq-23.2.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:20bafc4095eab00f41a510579363a3f5e1f5c69d7ee10f1d88895c4df0259183"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/6b/36/0546d92a57ca60a456f801f4e1a55932c8c6e324e1b77f6faca660728b4e/pyzmq-23.2.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:90d88f9d9a2ae6cfb1dc4ea2d1710cdf6456bc1b9a06dd1bb485c5d298f2517e"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/72/37/d5603f352522e249e44ee767a8a59b3fe7cf7f708a94fd40a637c6890add/pyzmq-23.2.1.tar.gz", hash = "sha256:2b381aa867ece7d0a82f30a0c7f3d4387b7cf2e0697e33efaa5bed6c5784abcd"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/7a/1b/af3395604377973dafa631bcf5e4e6e2de8230072656738a4ed57354e8c7/pyzmq-23.2.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8c02a0cd39dc01659b3d6cb70bb3a41aebd9885fd78239acdd8d9c91351c4568"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/7b/fe/a2cdefffdbb09c8d482bcb417e92be7f68282d7f595d529bbd7e957e3290/pyzmq-23.2.1-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:a0f09d85c45f58aa8e715b42f8b26beba68b3b63a8f7049113478aca26efbc30"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/7e/a7/5ba117b131c6a4bbc49b98fda619dfb61cee726a53196153063f69c8b806/pyzmq-23.2.1-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:ad28ddb40db8e450d7d4bf8a1d765d3f87b63b10e7e9a825a3c130c6371a8c03"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/8a/06/63027f96abc607d88adc6f2036875c9bf7aac530f374e2d7f41d2040338a/pyzmq-23.2.1-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c890309296f53f9aa32ffcfc51d805705e1982bffd27c9692a8f1e1b8de279f4"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/91/89/d970549354fb141bbd6baa62a8fd93eb9f02ee888e64c1998eb14bbb25e5/pyzmq-23.2.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:55568a020ad2cae9ae36da6058e7ca332a56df968f601cbdb7cf6efb2a77579a"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/92/b0/e763d08e8c6d8c4ca95bced7804729973e355889c7962fd7881f5820e422/pyzmq-23.2.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:415ff62ac525d9add1e3550430a09b9928d2d24a20cc4ce809e67caac41219ab"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/97/cf/6478e7292d10bc9d285cb2f7862bcc81bbefe2de884ca926f0535603644b/pyzmq-23.2.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:48400b96788cdaca647021bf19a9cd668384f46e4d9c55cf045bdd17f65299c8"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/99/80/d0942cd6716fee8a41019b8f92274358a8e20e413462f1f5eb36d90aa423/pyzmq-23.2.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2141e6798d5981be04c08996d27962086a1aa3ea536fe9cf7e89817fd4523f86"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/9d/1f/a5d305549110853f6d6e3cf3423b3e14655f4bb30cee96b50994f4d22389/pyzmq-23.2.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:12e62ff0d5223ec09b597ab6d73858b9f64a51221399f3cb08aa495e1dff7935"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/9d/d5/a10a1be96ec28a09f1700f1912ee1e04042b83d4e14f4fa7643d20a60a3b/pyzmq-23.2.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:79a87831b47a9f6161ad23fa5e89d5469dc585abc49f90b9b07fea8905ae1234"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/a1/46/ba94ad2e20c69b72867d11af5dfa0fd317840acea00153058e89561bad59/pyzmq-23.2.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:4d6f110c56f7d5b4d64dde3a382ae61b6d48174e30742859d8e971b18b6c9e5c"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/a1/ff/812ebb123b3cea42b7855c8355463115dff07368ed11be171c44e6b2c125/pyzmq-23.2.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:efb9e38b2a590282704269585de7eb33bf43dc294cad092e1b172e23d4c217e5"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/a2/9e/c2dd5f912d4d90fe7357f4980061c1d00318124042c1dddd063c2520a035/pyzmq-23.2.1-cp310-cp310-win_amd64.whl", hash = "sha256:650389bbfca73955b262b2230423d89992f38ec48033307ae80e700eaa2fbb63"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/a6/f9/5300939686535543c5954011f4ffc429dc85d0f3f079841dd6df2843ef0b/pyzmq-23.2.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:38e106b64bad744fe469dc3dd864f2764d66399178c1bf39d45294cc7980f14f"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/a7/2c/9ff05957a40dc87889a584457a6c700e77ad3f623e4f5e33a29dfcc2ea59/pyzmq-23.2.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:794871988c34727c7f79bdfe2546e6854ae1fa2e1feb382784f23a9c6c63ecb3"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/a7/bb/54986ab979a4f964c6b76817b6fdd7403a9cf76f368a0c67ec6bb65a783d/pyzmq-23.2.1-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:39dd252b683816935702825e5bf775df16090619ced9bb4ba68c2d0b6f0c9b18"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/a8/d9/8da216639eff155dc0549cce52aed765c6667dba56a38a38b81c3e0e4adb/pyzmq-23.2.1-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:67975a9e1237b9ccc78f457bef17691bbdd2055a9d26e81ee914ba376846d0ce"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/ae/8e/1d806b8f90b2ba994532b7050bab4ca56eb537696f7d3e2ea16c0c37dc68/pyzmq-23.2.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9a39ddb0431a68954bd318b923230fa5b649c9c62b0e8340388820c5f1b15bd2"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/b2/04/f4b318dd471df5269e0947dd0f932c8c6ba492af42a78f48a2a224e99a6d/pyzmq-23.2.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:71b32a1e827bdcbf73750e60370d3b07685816ff3d8695f450f0f8c3226503f8"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/b4/e3/081b1a02af85b60e19191ea5d41b422ea7a0126043b7c54b5f3c2ce8e065/pyzmq-23.2.1-cp311-cp311-macosx_10_15_universal2.whl", hash = "sha256:e753eee6d3b93c5354e8ba0a1d62956ee49355f0a36e00570823ef64e66183f5"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/b6/a0/79ae7abdc28eecc261806a9ebbfb03f05709a501350009c5925e0ed73a29/pyzmq-23.2.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:c56b1a62a1fb87565343c57b6743fd5da6e138b8c6562361d7d9b5ce4acf399a"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/b7/90/da3761e269f7d5a7916e98364f55745ca1a979a6316a265fc4b4ac26e144/pyzmq-23.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:ec9803aca9491fd6f0d853d2a6147f19f8deaaa23b1b713d05c5d09e56ea7142"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/b7/ac/18b75626cede66295a27e94d7cfe301d2d35120b200a6a46f205a171a20e/pyzmq-23.2.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e0113d70b095339e99bb522fe7294f5ae6a7f3b2b8f52f659469a74b5cc7661"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/ba/7f/bd00e5fb931a993d53962c9d9a88855a2b896bc07245d0570bbc4f94905c/pyzmq-23.2.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:fefdf9b685fda4141b95ebec975946076a5e0723ff70b037032b2085c5317684"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/ba/a6/f524227891f93abd129e05ee62eb3a9b3ded4c65ee4f20e7ad4fc86d82b0/pyzmq-23.2.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:8dc66f109a245653b19df0f44a5af7a3f14cb8ad6c780ead506158a057bd36ce"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/ba/af/866b9970b30efb1c1e649eabf5f79c731c8268e6a1c0d3ef17c5c972daca/pyzmq-23.2.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:407f909c4e8fde62fbdad9ebd448319792258cc0550c2815567a4d9d8d9e6d18"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/ba/c7/89a6641ecd278075d7d81794580765ab72284e001b9a319620e04d7d215a/pyzmq-23.2.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:8c842109d31a9281d678f668629241c405928afbebd913c48a5a8e7aee61f63d"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/be/7e/a315e462440b06ebc06fcd31a7cdf6df6b49d150c7da8afacd4c7e393740/pyzmq-23.2.1-cp36-cp36m-win32.whl", hash = "sha256:565bd5ab81f6964fc4067ccf2e00877ad0fa917308975694bbb54378389215f8"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/c0/46/77ccf7c1b4c4ba3c33135f4b54b58292b640f17bcefa7209ae2af1f96fef/pyzmq-23.2.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:49d30ba7074f469e8167917abf9eb854c6503ae10153034a6d4df33618f1db5f"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/c0/61/0ae8044599496c3bd72b27e8ee9d120a2e16c73726eba6c9b38bb9c295ff/pyzmq-23.2.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c9cfaf530e6a7ff65f0afe275e99f983f68b54dfb23ea401f0bc297a632766b6"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/cc/29/9a6474f34c3f1a0a9cc828a7dbe08ff51243d2341055a43fc23f4782665a/pyzmq-23.2.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:f619fd38fc2641abfb53cca719c165182500600b82c695cc548a0f05f764be05"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/cd/88/dcbe0bfc6b744badda43322e2538ab269451e0f298d3e4616da92a25dfa3/pyzmq-23.2.1-cp311-cp311-win32.whl", hash = "sha256:c3ebf1668664d20c8f7d468955f18379b7d1f7bc8946b13243d050fa3888c7ff"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/d0/de/706efed0f5258336903dc5af0417896e59fac51ce363f406a461b330eada/pyzmq-23.2.1-cp39-cp39-win_amd64.whl", hash = "sha256:5e05492be125dce279721d6b54fd1b956546ecc4bcdfcf8e7b4c413bc0874c10"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/d3/f8/561eb1b832bb4c360c9071e9a2945efa19b8bf5a10488c7b85573df97fcb/pyzmq-23.2.1-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:c780acddd2934c6831ff832ecbf78a45a7b62d4eb216480f863854a8b7d54fa7"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/d7/1e/ece1805e6728fbb5faf77035a4d00af37bf48bff0300a563b6460d7cdf8b/pyzmq-23.2.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c558b50402fca1acc94329c5d8f12aa429738904a5cfb32b9ed3c61235221bb"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/db/11/d9c1960fca3c5543c40dab10da86b793793a572b3fcb5b741accaed7aca8/pyzmq-23.2.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:4bb798bef181648827019001f6be43e1c48b34b477763b37a8d27d8c06d197b8"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/dc/24/3ac8d73b09a6db9d26d4c6fb454101dbc9e1ea1e6df50cd50041decbd895/pyzmq-23.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4805af9614b0b41b7e57d17673459facf85604dac502a5a9244f6e8c9a4de658"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/dd/2c/9082402d9662f0b4aee6e35aaa99dc340805156ab21ad552a00a2e19a03a/pyzmq-23.2.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:f392cbea531b7142d1958c0d4a0c9c8d760dc451e5848d8dd3387804d3e3e62c"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/df/ea/864585c7e84b2cef73a213214714f84c3f9e334a5d981eff3d5f21a832dd/pyzmq-23.2.1-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:29b74774a0bfd3c4d98ac853f0bdca55bd9ec89d5b0def5486407cca54472ef8"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/e1/10/ce0e374361129428eb2c96b9b9193d111f1804566e2f3c753201989265d3/pyzmq-23.2.1-cp310-cp310-macosx_10_15_universal2.whl", hash = "sha256:a3fd44b5046d247e7f0f1660bcafe7b5fb0db55d0934c05dd57dda9e1f823ce7"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/e2/b6/da9a959b7f86612fc534e61b368bacd665b4af8efe3feb4e8fd1f65600e0/pyzmq-23.2.1-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:35e635343ff367f697d00fa1484262bb68e36bc74c9b80737eac5a1e04c4e1b1"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/e5/1a/ef08406d572e52d740d9dfa508572d54106fdf422a634f944ba9968021be/pyzmq-23.2.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b861db65f6b8906c8d6db51dde2448f266f0c66bf28db2c37aea50f58a849859"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/e7/5e/1305affea185ae876606ad9e4b22cc7072a58d3d9ec5df757adedb4546be/pyzmq-23.2.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:9d0ab2936085c85a1fc6f9fd8f89d5235ae99b051e90ec5baa5e73ad44346e1f"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/e9/58/8a5ea2681d7f7d07c29534b45ae1dbd48412db38a097616bff05a7927d85/pyzmq-23.2.1-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e06747014a5ad1b28cebf5bc1ddcdaccfb44e9b441d35e6feb1286c8a72e54be"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/f5/bd/3be4e01170087f6726899085488cb1ee9aee985967adc67b757077755fc7/pyzmq-23.2.1-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:929d548b74c0f82f7f95b54e4a43f9e4ce2523cfb8a54d3f7141e45652304b2a"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/f9/fe/da99084c6207b646024931ee32fb32f73ca068ba9837857f8c6f182f9de1/pyzmq-23.2.1-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:a114992a193577cb62233abf8cb2832970f9975805a64740e325d2f895e7f85a"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/fa/f2/145555b47bd3a941d5847b4c975132503df6616bc92e2810cdc7fcb3005a/pyzmq-23.2.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:aecd6ceaccc4b594e0092d6513ef3f1c0fa678dd89f86bb8ff1a47014b8fca35"},
]
"rfc3986 1.5.0" = [
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/79/30/5b1b6c28c105629cc12b33bdcbb0b11b5bb1880c6cfbd955f9e792921aa8/rfc3986-1.5.0.tar.gz", hash = "sha256:270aaf10d87d0d4e095063c65bf3ddbc6ee3d0b226328ce21e036f946e421835"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/c4/e5/63ca2c4edf4e00657584608bee1001302bbf8c5f569340b78304f2f446cb/rfc3986-1.5.0-py2.py3-none-any.whl", hash = "sha256:a86d6e1f5b1dc238b218b012df0aa79409667bb209e58da56d0b94704e712a97"},
]
"rich 12.5.1" = [
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/bb/2d/c902484141330ded63c6c40d66a9725f8da5e818770f67241cf429eef825/rich-12.5.1.tar.gz", hash = "sha256:63a5c5ce3673d3d5fbbf23cd87e11ab84b6b451436f1b7f19ec54b6bc36ed7ca"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/f6/39/4cb526e0d505464376e3c47a812df6e6638363ebe66e6a63618831fe47ad/rich-12.5.1-py3-none-any.whl", hash = "sha256:2eb4e6894cde1e017976d2975ac210ef515d7548bc595ba20e195fb9628acdeb"},
]
"setuptools 65.3.0" = [
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/cc/83/7ea9d9b3a6ff3225aca2fce5e4df373bee7e0a74c539711a4fbfda53374f/setuptools-65.3.0.tar.gz", hash = "sha256:7732871f4f7fa58fb6bdcaeadb0161b2bd046c85905dbaa066bdcbcc81953b57"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/d9/5f/2daccd14278b6b780ae6799f85998377c06019354982391245f4b58a927d/setuptools-65.3.0-py3-none-any.whl", hash = "sha256:2e24e0bec025f035a2e72cdd1961119f557d78ad331bb00ff82efb2ab8da8e82"},
]
"six 1.16.0" = [
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/71/39/171f1c67cd00715f190ba0b100d606d440a28c93c7714febeca8b79af85e/six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/d9/5a/e7c31adbe875f2abbb91bd84cf2dc52d792b5a01506781dbcf25c91daf11/six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"},
]
"sniffio 1.2.0" = [
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/52/b0/7b2e028b63d092804b6794595871f936aafa5e9322dcaaad50ebf67445b3/sniffio-1.2.0-py3-none-any.whl", hash = "sha256:471b71698eac1c2112a40ce2752bb2f4a4814c22a54a3eed3676bc0f5ca9f663"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/a6/ae/44ed7978bcb1f6337a3e2bef19c941de750d73243fc9389140d62853b686/sniffio-1.2.0.tar.gz", hash = "sha256:c4666eecec1d3f50960c6bdf61ab7bc350648da6c126e3cf6898d8cd4ddcd3de"},
]
"stack-data 0.5.0" = [
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/9d/ad/22b5d86e421b2786aeb166cf51d519ce5a2a8878c7542d3e58e75aac02b5/stack_data-0.5.0-py3-none-any.whl", hash = "sha256:66d2ebd3d7f29047612ead465b6cae5371006a71f45037c7e2507d01367bce3b"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/d6/3a/6baf4a5e7b48f00bc636bc878c6d93afd032dfeafc10b4a0a5a27232efb3/stack_data-0.5.0.tar.gz", hash = "sha256:715c8855fbf5c43587b141e46cc9d9339cc0d1f8d6e0f98ed0d01c6cb974e29f"},
]
"tomli 2.0.1" = [
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/97/75/10a9ebee3fd790d20926a90a2547f0bf78f371b2f13aa822c759680ca7b9/tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/c0/3f/d7af728f075fb08564c5949a9c95e44352e23dee646869fa104a3b2060a3/tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"},
]
"tornado 6.2" = [
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/11/30/ac70f5c5f03cf1cd0ae8199c80382387a9fe57e8f68853d5c9527c0219e5/tornado-6.2-cp37-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b8150f721c101abdef99073bf66d3903e292d851bee51910839831caba341a75"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/19/bb/b6c3d1668d2b10ad38a584f3a1ec9737984e274f8b708e09fcbb96427f5c/tornado-6.2-cp37-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d3a2f5999215a3a06a4fc218026cd84c61b8b2b40ac5296a6db1f1451ef04c1e"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/1c/26/cbfa1103e74a02e09dd53291e419da3ad4c5b948f52aea5800e6671b56e0/tornado-6.2-cp37-abi3-win_amd64.whl", hash = "sha256:e5f923aa6a47e133d1cf87d60700889d7eae68988704e20c75fb2d65677a8e4b"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/5c/0c/cbc0a98f7b8ef833bcb13c58d35d09e2c288ae67a35af4c8960b88f99ae9/tornado-6.2-cp37-abi3-macosx_10_9_x86_64.whl", hash = "sha256:87dcafae3e884462f90c90ecc200defe5e580a7fbbb4365eda7c7c1eb809ebc9"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/60/08/e630a348b34a9ddd640aed67dafc6f0df425d8ac07d2fa60288f38321c69/tornado-6.2-cp37-abi3-musllinux_1_1_i686.whl", hash = "sha256:6fdfabffd8dfcb6cf887428849d30cf19a3ea34c2c248461e1f7d718ad30b66b"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/71/cc/c1342382484d0178a79029109c433e406a60095da1c3605ca966775a70e5/tornado-6.2-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ba09ef14ca9893954244fd872798b4ccb2367c165946ce2dd7376aebdde8e3ac"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/cd/a4/761e45cea12b2af076d36240d464b371ab1231272948cdc49b7d81855c5c/tornado-6.2-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:5f8c52d219d4995388119af7ccaa0bcec289535747620116a58d830e7c25d8a8"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/ec/01/93e63530851ba8ef9685f1a9b91e324b28d28323a6b67400114ea65c5110/tornado-6.2-cp37-abi3-win32.whl", hash = "sha256:5c87076709343557ef8032934ce5f637dbb552efa7b21d08e89ae7619ed0eb23"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/f3/9e/225a41452f2d9418d89be5e32cf824c84fe1e639d350d6e8d49db5b7f73a/tornado-6.2.tar.gz", hash = "sha256:9b630419bde84ec666bfd7ea0a4cb2a8a651c2d5cccdbdd1972a0c859dfc3c13"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/f9/51/6f63a166d9a3077be100cbb13dcbce434e5654daaaa7003b0a045b9f6edf/tornado-6.2-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:1d54d13ab8414ed44de07efecb97d4ef7c39f7438cf5e976ccd356bebb1b5fca"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/fb/bd/074254a55bfc82d7a1886abbd803600ef01cbd76ee66bc30307b2724130b/tornado-6.2-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:20f638fd8cc85f3cbae3c732326e96addff0a15e22d80f049e00121651e82e72"},
]
"traitlets 5.3.0" = [
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/83/a9/1059771062cb80901c34a4dea020e76269412e69300b4ba12e3356865ad8/traitlets-5.3.0-py3-none-any.whl", hash = "sha256:65fa18961659635933100db8ca120ef6220555286949774b9cfc106f941d1c7a"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/b2/ed/3c842dbe5a8f0f1ebf3f5b74fc1a46601ed2dfe0a2d256c8488d387b14dd/traitlets-5.3.0.tar.gz", hash = "sha256:0bb9f1f9f017aa8ec187d8b1b2a7a6626a2a1d877116baba52a129bfa124f8e2"},
]
"typing-extensions 4.3.0" = [
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/9e/1d/d128169ff58c501059330f1ad96ed62b79114a2eb30b8238af63a2e27f70/typing_extensions-4.3.0.tar.gz", hash = "sha256:e6d2677a32f47fc7eb2795db1dd15c1f34eff616bcaf2cfb5e997f854fa1c4a6"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/ed/d6/2afc375a8d55b8be879d6b4986d4f69f01115e795e36827fd3a40166028b/typing_extensions-4.3.0-py3-none-any.whl", hash = "sha256:25642c956049920a5aa49edcdd6ab1e06d7e5d467fc00e0506c44ac86fbfca02"},
]
"wcwidth 0.2.5" = [
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/59/7c/e39aca596badaf1b78e8f547c807b04dae603a433d3e7a7e04d67f2ef3e5/wcwidth-0.2.5-py2.py3-none-any.whl", hash = "sha256:beb4802a9cebb9144e99086eff703a642a13d6a0052920003a230f3294bbe784"},
{url = "https://pypi.tuna.tsinghua.edu.cn/packages/89/38/459b727c381504f361832b9e5ace19966de1a235d73cdbdea91c771a1155/wcwidth-0.2.5.tar.gz", hash = "sha256:c4d647b99872929fdb7bdcaa4fbe7f01413ed3d98077df798530e5b04f116c83"},
]

View File

@ -79,14 +79,40 @@ func (m PythonPackage) OwnedFiles() (result []string) {
return result return result
} }
// PythonPdmLockExtraVariant represents a specific extras combination variant within a PDM lock file.
// PDM creates separate package entries for different extras combinations; this struct captures those variants.
type PythonPdmLockExtraVariant struct {
// Extras are the optional extras enabled for this variant (e.g., ["toml"], ["dev"], or ["toml", "dev"])
Extras []string `json:"extras"`
// Dependencies are the dependencies specific to this extras variant
Dependencies []string `json:"dependencies,omitempty"`
// Files are the package files specific to this variant (only populated if different from base)
Files []PythonPdmFileEntry `json:"files,omitempty"`
// Marker is the environment conditional expression for this variant (e.g., "python_version < \"3.11\"")
Marker string `json:"marker,omitempty"`
}
// PythonPdmLockEntry represents a single package entry within a pdm.lock file. // PythonPdmLockEntry represents a single package entry within a pdm.lock file.
type PythonPdmLockEntry struct { type PythonPdmLockEntry struct {
// Summary provides a description of the package // Summary provides a description of the package
Summary string `mapstructure:"summary" json:"summary" toml:"summary"` Summary string `mapstructure:"summary" json:"summary"`
// Files are the package files with their paths and hash digests // Files are the package files with their paths and hash digests (for the base package without extras)
Files []PythonFileRecord `mapstructure:"files" json:"files" toml:"files"` Files []PythonPdmFileEntry `mapstructure:"files" json:"files"`
// Dependencies are the dependency specifications, without environment qualifiers // Marker is the "environment" --conditional expressions that determine whether a package should be installed based on the runtime environment
Dependencies []string `mapstructure:"dependencies" json:"dependencies" toml:"dependencies"` Marker string `mapstructure:"marker" json:"marker,omitempty"`
// RequiresPython specifies the Python version requirement (e.g., ">=3.6").
RequiresPython string `mapstructure:"RequiresPython" json:"requiresPython,omitempty" `
// Dependencies are the dependency specifications for the base package (without extras)
Dependencies []string `mapstructure:"dependencies" json:"dependencies,omitempty"`
// Extras contains variants for different extras combinations (PDM may have multiple entries per package)
Extras []PythonPdmLockExtraVariant `json:"extras,omitempty"`
}
type PythonPdmFileEntry struct {
// URL is the file download URL
URL string `mapstructure:"url" json:"url"`
// Digest is the hash digest of the file hosted at the URL
Digest PythonFileDigest `mapstructure:"hash" json:"digest"`
} }
// PythonPipfileLockEntry represents a single package entry within a Pipfile.lock file. // PythonPipfileLockEntry represents a single package entry within a Pipfile.lock file.